fix(tools): correct key check in access_chain of access module

The old check evaluates the expression before determining whether the
resulting value is defined. However, when the expression refers to a
subroutine, it gets executed; if the subroutine doesn't protect against
missing parameters, it'll cause executions with bad input, i.e., the
Striker->generate_manifest subroutine without parameters.

The new check uses can(), which correctly determines whether the key
"exists" on the blessed object; although it doesn't strictly mean
"exists", but it does the job.
main
Tsu-ba-me 1 year ago
parent ee259f5a3a
commit 7845f8c170
  1. 11
      tools/anvil-access-module

@ -170,7 +170,7 @@ sub access_chain
my @chain = split(/->|[.]/, $chain_str); my @chain = split(/->|[.]/, $chain_str);
my $key_index = 0; my $key_index = 0;
my $intermediate = $anvil; my $intermediate = $anvil;
my @results; my @results = (1);
foreach my $key (@chain) foreach my $key (@chain)
{ {
@ -192,14 +192,15 @@ sub access_chain
} }
else # Left-hand is not hash; treat it as blessed/class object (module) and try to call a method from it else # Left-hand is not hash; treat it as blessed/class object (module) and try to call a method from it
{ {
# Key not found in object; stop following the chain # Don't continue follow the chain when key if not found
eval { defined $intermediate->${key} ? 1 : 0; } or last; # Note: can() results in truthy when key refers to something that can return a value
eval { $intermediate->can($key) } or last;
# On the last key of the chain; try to execute the subroutine if it exists # On the last key of the chain; try to execute the subroutine if it exists
if ( $is_last_key && $intermediate->can($key) ) if ($is_last_key)
{ {
# Trailing 1 means the eval block will return success if the subroutine and assign succeeded # Trailing 1 means the eval block will return success if the subroutine and assign succeeded
eval { (@results) = $intermediate->${key}(@$chain_args); 1; } or @results = (1); eval { (@results) = $intermediate->${key}(@$chain_args); 1; };
last; last;
} }

Loading…
Cancel
Save