Reputation: 33
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
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