php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49446 escapeshellarg dosn`t work on windows
Submitted: 2009-09-02 23:10 UTC Modified: 2017-10-24 07:37 UTC
Votes:7
Avg. Score:4.3 ± 0.9
Reproduced:5 of 5 (100.0%)
Same Version:2 (40.0%)
Same OS:3 (60.0%)
From: heromantor at users dot sourceforge dot net Assigned:
Status: Open Package: CGI/CLI related
PHP Version: 5.2.10 OS: windows xp sp2
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: heromantor at users dot sourceforge dot net
New email:
PHP Version: OS:

 

 [2009-09-02 23:10 UTC] heromantor at users dot sourceforge dot net
Description:
------------
escapeshellarg function dosn`t work properly on windows platform. Problem in " \ and % chars handling.

this patch fix this problem
--- exec.c  Wed Sep  2 22:41:27 2009
+++ exec_fixed.c    Wed Sep  2 22:40:50 2009
@@ -352,6 +352,11 @@
    cmd = safe_emalloc(4, l, 3); /* worst case */
 
 #ifdef PHP_WIN32
+#   define PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES() \
+        for(j = y - 1; j > 0 && cmd[j] == '\\'; --j) { \
+            cmd[y++] = '\\'; \
+        }
+
    cmd[y++] = '"';
 #else
    cmd[y++] = '\'';
@@ -372,10 +377,16 @@
 
        switch (str[x]) {
 #ifdef PHP_WIN32
-       case '"':
-       case '%':
-           cmd[y++] = ' ';
-           break;
+        case '%':
+            PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+            cmd[y++] = '"';
+            cmd[y++] = '%';
+            cmd[y++] = '"';
+            break;
+        case '"':
+            PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+            cmd[y++] = '"';
+            /* fall-through */
 #else
        case '\'':
            cmd[y++] = '\'';
@@ -388,6 +399,9 @@
        }
    }
 #ifdef PHP_WIN32
+    PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+#   undef PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES
+
    cmd[y++] = '"';
 #else
    cmd[y++] = '\'';

and some test cases
P A T H => "P A T H"
%PATH% => ""%"PATH"%""
a%PATH%b => "a"%"PATH"%"b"
%%PATH%% => ""%""%"PATH"%""%""
"PATH" => """PATH"""
"%PATH%" => """"%"PATH"%""""
\P\A\T\H => "\P\A\T\H"
\P\A\T\H\ => "\P\A\T\H\\"
\%\%\ => "\\"%"\\"%"\\"
a\\%b\\c%\\ => "a\\\\"%"b\\c"%"\\\\"
"a\" => """a\\"""
a\" => "a\\"""
a\"^|^&^(^) => "a\\""^|^&^(^)"
PATH\%\ => "PATH\\"%"\\"


Reproduce code:
---------------
<?php
print_r(escapeshellarg("%PATH%") . PHP_EOL);
print_r(escapeshellarg("c:\\temp\\") . PHP_EOL);
print_r(escapeshellarg('\\"') . PHP_EOL);


Expected result:
----------------
""%"PATH"%""
"c:\temp\\"
"\\"""


Actual result:
--------------
" PATH "
"c:\temp\"
"\ "


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-09-02 23:51 UTC] heromantor at users dot sourceforge dot net
oh sorry, i post invalid patch.

this ok:
--- exec.c  Wed Sep  2 23:44:19 2009
+++ exec_fixed.c    Wed Sep  2 23:44:41 2009
@@ -343,7 +343,7 @@
  */
 PHPAPI char *php_escape_shell_arg(char *str)
 {
-    int x, y = 0, l = strlen(str);
+    int x, y = 0, j, l = strlen(str);
     char *cmd;
     size_t estimate = (4 * l) + 3;
 
@@ -352,6 +352,11 @@
     cmd = safe_emalloc(4, l, 3); /* worst case */
 
 #ifdef PHP_WIN32
+#   define PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES() \
+        for(j = y - 1; j > 0 && cmd[j] == '\\'; --j) { \
+            cmd[y++] = '\\'; \
+        }
+
     cmd[y++] = '"';
 #else
     cmd[y++] = '\'';
@@ -372,10 +377,16 @@
 
         switch (str[x]) {
 #ifdef PHP_WIN32
-        case '"':
-        case '%':
-            cmd[y++] = ' ';
-            break;
+        case '%':
+            PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+            cmd[y++] = '"';
+            cmd[y++] = '%';
+            cmd[y++] = '"';
+            break;
+        case '"':
+            PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+            cmd[y++] = '"';
+            /* fall-through */
 #else
         case '\'':
             cmd[y++] = '\'';
@@ -388,6 +399,9 @@
         }
     }
 #ifdef PHP_WIN32
+    PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES()
+#   undef PHP_ESCAPE_SHELL_ARG_PROCESS_TRAILING_SLASHES
+
     cmd[y++] = '"';
 #else
     cmd[y++] = '\'';
 [2009-09-03 04:16 UTC] scottmac@php.net
This was fixed in 5.3 with bug #43261

Though \\ within double quotes is considered a single \
 [2009-09-11 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2011-03-03 10:54 UTC] pajoye@php.net
-Status: Closed +Status: Assigned -Assigned To: +Assigned To: pajoye
 [2011-03-03 10:54 UTC] pajoye@php.net
Something is wrong with this patch, and we should try to use ^ in trunk.
 [2016-06-21 16:34 UTC] cmb@php.net
FWIW, I've just tested with PHP 7.0.7:

    <?php
    var_dump(escapeshellarg("%PATH%"));
    var_dump(escapeshellarg("c:\\temp\\"));
    var_dump(escapeshellarg('\\"'));
    ?>

Result:

    string(8) "" PATH ""
    string(11) ""c:\temp\\""
    string(4) ""\ ""

With regard to the documentation (3) is correct, but (1) and (2)
would be wrong:

| On Windows, escapeshellarg() instead removes percent signs,
| replaces double quotes with spaces and adds double quotes around
| the string.

The documentation also doesn't yet mention that exclamation marks
are replaced by spaces.

I'll fix the doc bugs right away.

Anyhow, I'd like to see:

    string(10) ""^%PATH^%""
    string(10) ""c:\temp\""
    string(3) "\"""
 [2016-06-21 17:00 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=339439
Log: Fix Windows related documentation (see #49446)
 [2017-10-24 07:37 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: pajoye +Assigned To:
 [2018-04-14 13:01 UTC] micke dot andrsn at gmail dot com
Here is a PHP library which escapes everything correctly on Windows, if you want to port the algorithm to native C code:

https://github.com/johnstevenson/winbox-args/blob/master/src/Args.php
 [2023-05-25 05:14 UTC] tourtraveltipsinc at gmail dot com
Tour Travel Tips Inc are tour,destination, beaches, hotels, resturants etc. More info to visit:(https://tourtraveltipsinc.com)github.com
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 15:01:30 2024 UTC