Let's look at the code:
use strict; use warnings; sub mysub($$) { my ($a, $b) = @_; print "$a\n"; print "$b\n"; } my $x = undef; mysub($x && $x->[0] =~ /abc/, $x = []);
Can mysub get something that is true in boolean context as the first argument?
')
It would seem not, because for this $ x should be a reference to an array, and its first element should contain the substring 'abc'
But it turned out that it can
$perl poc.pl ARRAY(0xdb6d48) ARRAY(0xdb6d48)
What's the matter?
- in Perl (as in many other languages) X && Y , in case X is false, will return not just false (without performing Y ), but return X itself (which must be false)
- All parameters in Perl are passed by reference, not by value.
Thus, when the first argument is calculated
$x && $x->[0] =~ /abc/
$ x is undef ie false, therefore instead of the first argument, $ x itself is passed,
when the second argument is calculated, $ x is assigned the value [] (reference to an empty array), so when the mysub code starts executing, both arguments
reference to $ x (which is an empty array, which, in turn, is true)
If it seems that the code does not look very applicable in practice, then I can say that the bug was found in the real unit test code:
ok( ($errors && ($errors->[0] =~ /My Exception/i)), "should catch exception $errors->[0]" );
(this also triggers another great feature of the
Autovivification pearl - if you access $ errors -> [0], then $ errors will be created,
if $ errors was previously undef)