简体   繁体   中英

Perl equivalent of PHP's escapeshellarg

To escape the string to be used as shell argument we use the function escapeshellarg() in PHP . Does Perl have an equivalent function ?

String::ShellQuote , but most of the time this is not needed. You simply can avoid invoking the shell by careful programming. For example, system takes a list of arguments instead of a string.

Best practice:

use IPC::System::Simple qw(systemx);
systemx($command, @arguments);

require IPC::System::Simple;
use autodie qw(:all);
system([@allowed_exit_values], $command, @arguments);

Perl can match the following stated function:

adds single quotes around a string and quotes/escapes any existing single quotes

http://php.net/manual/en/function.escapeshellarg.php#function.escapeshellarg

like this:

sub php_escapeshellarg { 
    my $str = @_ ? shift : $_;
    $str =~ s/((?:^|[^\\])(?:\\\\)*)'/$1'\\''/g;
    return "'$str'";
}

I have to agree with @daxim. But there are some circumstances where you can't use this like passing a command over a socket to a program that isn't perl or doesn't have IPC module available. I also looked at the regexp given by @axeman and that seems a bit complex to me. I could be wrong, but I think you don't need to escape backslashes in single quoted strings for a command. So, you could just do this:

sub escapeshellarg {
    my $arg = shift;

    $arg =~ s/'/'\\''/g;
    return "'" . $arg . "'";
}

If anyone has any reason, why this may be insecure, I would like to know. I have tested it using any kind of trickery I could think of to make the shell execute arbitrary code, without success, which makes me think this regexp is the same as the PHP implementation.

In the PHP implementation, it states that all it does is: adds single quotes around a string and quotes/escapes any existing single quotes.

Which is the only thing this regexp does. Thoughts?

This one works for me in BASH:

sub escape_shell_param($) {
   my ($par) = @_;
   $par =~ s/'/'"'"'/g;  # "escape" all single quotes
   return "'$par'";      # single-quote entire string
 }

It's based on the following statements taken from the BASH man page:

  1. Enclosing characters in single quotes preserves the literal value of each character within the quotes.
  2. A single quote may not occur between single quotes, even when preceded by a backslash.
  3. Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \\, and, when history expansion is enabled, !.

From (2.) we know that backslash cannot be used to escape single qoutes, but from (3.) it's implied that double quotes preserve the literal value of (aka escape) single quotes.

Also note that the only purpose of quotes is to change the meaning of the quoted characters (no special string objects or similar things are created) and after expansion all consecutive literal characters are joined together. Then, 'foo''bar' is the same as foobar .

What the function above does is to single-quote the entire string so that no charcter in it has special meaning. However, to allow for the presence of single quote characters, the string is split wherever such characters are found, and the following operations are done: the previous substring is finalized ( ' ), then a double-quoted single quote is introduced ( "'" ) and the next substring is started ( ' ). That's why ' is globally replaced by '"'"' .

For example (pseudocode):

foo'bar => 'foo' + "'" + 'bar'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM