Home > Software design >  Type of arg 1 to keys must be hash error shows on Perl 5.10 but not Perl 5.16
Type of arg 1 to keys must be hash error shows on Perl 5.10 but not Perl 5.16

Time:05-13

I keep getting the following error:

Type of arg 1 to keys must be hash (not hash element)

at this line:

my $command = join(" ", @{$jparams{args}})
  . " -cp " . $jparams{cp}
  . " "     . $jparams{class}
  . " "     . join(" ",
     map {
       ${_} . "=" . qq|"$jparams{params}{$_}"|
     } keys $jparams{params}
  );

The error shows on Perl 5.10 but not Perl 5.16. How do I get it to work across both versions?

CodePudding user response:

keys $jparams{params}

should be

keys %{ $jparams{params} }

Your code suffers from code injection bugs.

If the command is passed to system (or exec), use its multi-argument form.

my @command = (
   @{ $jparams{ args } },
   -cp => $jparams{ cp },
   $jparams{ class },
   map { "$_=$jparams{ params }{ $_ }" }
      keys %{ $jparams{ params } },
);

system { $command[0] } @command;

Not only will this solve the problem, it will avoid needlessly spawning a shell.

But if you do need a shell command for some reason, your code injectiong bugs can be solved using String::ShellQuote's shell_quote.

my @command = (
   @{ $jparams{ args } },
   -cp => $jparams{ cp },
   $jparams{ class },
   map { "$_=$jparams{ params }{ $_ }" }
      keys %{ $jparams{ params } },
);

my $command = shell_quote( @command );

CodePudding user response:

You couldn't pass a reference to keys until Perl 5.14, but became an "experimental" warning in 5.20.

You can fix this by dereferencing the hashref:

keys %{ $jparams{params} }
  •  Tags:  
  • perl
  • Related