[...">
📜 ⬆️ ⬇️

Another way to shoot yourself in Perl

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?

  1. 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)
  2. 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)

Source: https://habr.com/ru/post/168559/


All Articles