minty_he
minty_he

Reputation: 33

Why an undef variable becomes {} without define?

I'm working on review webmin's source code.

($wuser) = grep { $_->{'name'} eq $in{'user'} } &acl::list_users();

If we pass $in{'user'} like ?user=notexist, variable $wuser will be undef, isn't it?

The abstract code descript what happened below.

# $wuser is undef now.
#die Dumper($wuser);
if($wuser){die 'not die here';}
        if ($wuser->{'pass'} eq 'x') {
                #never reach here.
                die 'not die in branch 1';
        }
        elsif ($wuser->{'pass'} eq '*LK*' ||
               $wuser->{'pass'} =~ /^\!/) {
                #never reach here too.
                die 'not die in branch 2';
        }
if($wuser){die 'so....why die here '.Dumper($wuser);}
# $wuser is {} now.
}

So...when and how an undef variable becomes {} without any define...

Upvotes: 3

Views: 121

Answers (1)

Dave Cross
Dave Cross

Reputation: 69244

The problem here is a Perl feature called "autovivification". Basically, it means that if you treat an undefined Perl variable as a type of reference, then Perl will create a reference of that type and store it in your variable.

So your problem starts when you execute this statement:

if ($wuser->{'pass'} eq 'x')

Perl sees you treating $wuser as a hash reference, so it creates an empty hash and stores a reference to that hash in $wuser. It can then look up the "pass" key in that hash and find that it doesn't exist.

Usually, this is seen as a feature. You can run code like:

my $hash; # created as undef
$hash->{foo}{bar}{baz} = 1;

And Perl will create this data structure for you:

{
  'foo' => {
    'bar' => {
      'baz' => 1
    }
  }
};

without you needing to go to the trouble of creating all the intermediate levels of the hash.

Of course, your code is rather artificial. You know that $wuser is false when you start looking for keys. All references are true, so a false reference can never contain keys.

Upvotes: 8

Related Questions