
Another way to shoot yourself in Perl
Let's look at the code:
Can mysub as the first argument get something that in the boolean context is true?
It would seem not, because for this $ x should be a reference to the array, and its first element should contain the substring 'abc'
But it turned out that it could
What is the matter?
Thus, when the first argument is calculated
$ x is undef i.e. false, therefore, instead of the first argument, $ x itself is passed
when the second argument is calculated, $ x is assigned the value [] (a reference to an empty array), so when mysub code starts to run, both arguments
contain a link to $ x (which is an empty array, which, in turn, is true)
If it seems that the code does not seem very applicable in practice, then I can say that the bug was found in the real unit test code:
(in this case, another wonderful feature of the Autovivification pearl is triggered - if you turn to $ errors -> [0] then $ errors will be created
if $ errors was undef before)
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 as the first argument get something that in the boolean context is true?
It would seem not, because for this $ x should be a reference to the array, and its first element should contain the substring 'abc'
But it turned out that it could
$perl poc.pl
ARRAY(0xdb6d48)
ARRAY(0xdb6d48)
What is the matter?
- in Perl (as in many other languages) X && Y , if X is false, will return not just false (without executing Y ), but X itself (which should 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 i.e. false, therefore, instead of the first argument, $ x itself is passed
when the second argument is calculated, $ x is assigned the value [] (a reference to an empty array), so when mysub code starts to run, both arguments
contain a link to $ x (which is an empty array, which, in turn, is true)
If it seems that the code does not seem 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]" );
(in this case, another wonderful feature of the Autovivification pearl is triggered - if you turn to $ errors -> [0] then $ errors will be created
if $ errors was undef before)