php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #43261 Use ^ as escape char for windows escapeshellcmd
Submitted: 2007-11-12 13:39 UTC Modified: 2008-07-22 16:22 UTC
From: RQuadling at GMail dot com Assigned: scottmac (profile)
Status: Closed Package: Program Execution
PHP Version: 5.3CVS-2007-11-12 (snap) OS: Windows XP SP2
Private report: No CVE-ID: None
 [2007-11-12 13:39 UTC] RQuadling at GMail dot com
Description:
------------
The windows version of escapeshellcmd replaces any of the special characters with a space, whereas, on other platforms it escapes them.

There is a valid escape character for windows. It is the ^ character.

Taking the current set of type-able characters from exec.c, the following is a proof of the ^ working ...

2007/11/12 13:22:42 V:\PHP\PHP5>echo foo ^' bar
foo ' bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^" bar
foo " bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^# bar
foo # bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^$ bar
foo $ bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^% bar
foo % bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^& bar
foo & bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^( bar
foo ( bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^) bar
foo ) bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^* bar
foo * bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^; bar
foo ; bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^? bar
foo ? bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^[ bar
foo [ bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^\ bar
foo \ bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^] bar
foo ] bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^^ bar
foo ^ bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^` bar
foo ` bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^{ bar
foo { bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^| bar
foo | bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^} bar
foo } bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^~ bar
foo ~ bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^< bar
foo < bar

2007/11/12 13:22:43 V:\PHP\PHP5>echo foo ^> bar
foo > bar

I can't easily emulate 0xA0 and 0xFF in this test.


I've included a patch also ...

Index: exec.c
===================================================================
RCS file: /repository/php-src/ext/standard/exec.c,v
retrieving revision 1.125
diff -u -r1.125 exec.c
--- exec.c	5 Nov 2007 14:06:19 -0000	1.125
+++ exec.c	12 Nov 2007 13:13:09 -0000
@@ -291,13 +291,12 @@
 			case '\\':
 			case '\x0A': /* excluding these two */
 			case '\xFF':
-#ifdef PHP_WIN32
-			/* since Windows does not allow us to escape these chars, just remove them */
 			case '%':
-				cmd[y++] = ' ';
-				break;
-#endif
+#ifdef PHP_WIN32
+				cmd[y++] = '^';
+#else
 				cmd[y++] = '\\';
+#endif
 				/* fall-through */
 			default:
 				cmd[y++] = str[x];



http://rquadling.php1h.com/exec.c.patch.txt

Reproduce code:
---------------
php -r "exec(escapeshellcmd('echo foo | bar'), $a, $b); var_dump($a, $b);"


Expected result:
----------------
array(1) {
  [0]=>
  string(10) "foo ^| bar"
}
int(0)

Actual result:
--------------
array(1) {
  [0]=>
  string(9) "foo   bar"
}
int(0)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-05-30 09:35 UTC] RQuadling at GMail dot com
Gee. Even with a patch, how do I get anyone to pay any attention!?
 [2008-06-10 10:12 UTC] kalle@php.net
Well if nobody else wanna apply it, then Ill take it =)
 [2008-06-10 10:20 UTC] kalle@php.net
Actually Scott fixed this without marking it as fixed =)
 [2008-06-10 12:10 UTC] pajoye@php.net
Assigned to Scott, needs more tests cases and explanation (as it may break a lot of scripts).
 [2008-07-22 16:22 UTC] scottmac@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Test added for this now.
 [2011-12-14 15:35 UTC] d dot kreuer at ibrams dot com
This issue is not fixed. It happened that I tried to use PHPUnit which escapes 
the command to invoke PHP. In my installation the php.exe can be found under the 
following path:

C:\Program Files (x86)\PHP\v5.3\php.exe

This is the default path for a PHP installation in combination with Windows and 
IIS (+ Platform Installer).
This path is currently escaped in the following way:

C:^\Program Files ^(x86^)^\PHP^\v5.3^\php.exe

Called from the commandline (which I assume is the same as called via exec()) 
the following happens:

C:\>C:^\Program Files ^(x86^)^\PHP^\v5.3^\php.exe
The command "C:\Program" is invalid or could not be found.

Even escaping the spaces does not work:

C:\>C:^\Program^ Files^ ^(x86^)^\PHP^\v5.3^\php.exe
Could not open input file: Files

Additionally surrounding the command with quotation marks which normally does 
not fail (because the spaces are threated as part of the command) does not work:

C:\>"C:^\Program Files ^(x86^)^\PHP^\v5.3^\php.exe"
The system cannot find the path specified.

If I run the command not escaped via escapeshellcmd() and only surrounded with 
quotes, it works.

C:\>"C:\Program Files (x86)\PHP\v5.3\php.exe" -v
PHP 5.3.8 (cli) (built: Aug 23 2011 12:14:39)

Used PHP Version is 5.3.8 (NTS) and OS is Windows 7.
 [2012-02-12 17:38 UTC] microsoftsux at gmx dot de
I can confirm this issue is not fixed as "d dot kreuer at ibrams dot com" stated.
The problem is, that windows does not require escaping characters if the path or argument is quoted. Since paths that contain whitespaces NEED TO BE quoted, they on the other hand MAY NOT be escaped.

So the solution would be to NOT escape the path/argument, if it contains whitespaces on windows within escapeshellcmd.
Additionally quoting the argument however, would be a breaking change - though correct implementation wise - because most applications up to now do this themself and double quoting is also not permitted.

Test cases:
C:\>C:\Dev\test(1)\test.bat
Der Befehl "C:\Dev\test" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>C:\Dev\test^(1^)\test.bat
'OK'

C:\>"C:\Dev\test^(1^)\test.bat"
Das System kann den angegebenen Pfad nicht finden.

C:\>"C:\Dev\test(1)\test.bat"
'OK'

C:\>C:\Dev\test (2)\test.bat
Der Befehl "C:\Dev\test" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>C:\Dev\test ^(2^)\test.bat
Der Befehl "C:\Dev\test" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>"C:\Dev\test ^(2^)\test.bat"
Das System kann den angegebenen Pfad nicht finden.

C:\>"C:\Dev\test (2)\test.bat"
'OK'
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Aug 24 02:01:27 2019 UTC