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 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?

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

    Also popular now: