Reputation: 13420
I found a very strange bug in my application today and I am not properly sure, how to fix it.
A form allows a user to do something. For this it needs to invoke a external command via system. So I decided to use escapeshellcmd
for this purpose.
<?php
$foo = "abc&d";
$bar = "abc d";
$command = sprintf("/bin/command '%s' '%s'", $foo, $bar);
var_dump(escapeshellcmd($command)); //"/bin/command 'abc\&d' 'abc d'"
?>
which is not what I wanted (note the wrong \&
which gives an extra, unwanted char '\').
So I came up with three different solutions and I don't know which one I should prefer, because only one gives me correct solution.
<?php
$foo = "abc&d";
$bar = "abc d";
$command1 = sprintf("/bin/command %s %s", $foo, $bar);
var_dump(escapeshellcmd($command1)); //"/bin/command abc\&d abc d" <- now we have three arguments
$command2 = sprintf("/bin/command %s %s", escapeshellarg($foo), escapeshellarg($bar));
var_dump($command2); //"/bin/command 'abc&d' 'abc d'" <- correct-ish?
$command3 = sprintf("/bin/command %s %s", escapeshellarg($foo), escapeshellarg($bar));
var_dump(escapeshellcmd($command3)); //"/bin/command 'abc\&d' 'abc d'" <- extra '\'
?>
Which of these solutions is prefered other the other? Why? Is there another (proper) solution for this dilemma?
Upvotes: 1
Views: 419
Reputation: 12017
You should use:
$command2 = sprintf("/bin/command %s %s", escapeshellarg($foo), escapeshellarg($bar));
var_dump($command2); //"/bin/command 'abc&d' 'abc d'" <- correct-ish?
The only reason you would ever want to use escapeshellcmd
is if you wanted to allow spaces within variables to separate arguments. If you just want to pass the arguments with escaping, use escapeshellarg
.
Upvotes: 1