Brendan McGrath : kernel32: Allow double quote style escape in argv.

Alexandre Julliard julliard at winehq.org
Fri Aug 23 09:31:23 CDT 2019


Module: wine
Branch: stable
Commit: bf1098a30a144042832103bc89b8879c7b577677
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=bf1098a30a144042832103bc89b8879c7b577677

Author: Brendan McGrath <brendan at redmandi.com>
Date:   Tue Feb 26 19:39:25 2019 +1100

kernel32: Allow double quote style escape in argv.

Two quotes together (within outer quotes) represents a single
quote (with the first quote acting as an escape character)

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46721
Signed-off-by: Brendan McGrath <brendan at redmandi.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 87917df887e00254a457a859c06892307b4e2daf)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/kernel32/process.c       | 17 +++++++++++++----
 dlls/kernel32/tests/process.c |  7 ++++---
 dlls/ntdll/process.c          | 17 +++++++++++++----
 3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 26c576e..f9f18d6 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1517,9 +1517,13 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
             /* '\', count them */
             bcount++;
         } else if ((*s=='"') && ((bcount & 1)==0)) {
-            /* unescaped '"' */
-            in_quotes=!in_quotes;
-            bcount=0;
+            if (in_quotes && s[1] == '"') {
+               s++;
+            } else {
+               /* unescaped '"' */
+               in_quotes=!in_quotes;
+               bcount=0;
+            }
         } else {
             /* a regular character */
             bcount=0;
@@ -1563,7 +1567,12 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
                  */
                 d-=bcount/2;
                 s++;
-                in_quotes=!in_quotes;
+                if(in_quotes && *s == '"') {
+                  *d++='"';
+                  s++;
+                } else {
+                  in_quotes=!in_quotes;
+                }
             } else {
                 /* Preceded by an odd number of '\', this is half that
                  * number of '\' followed by a '"'
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index fe68d28..f62f8fb 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -896,7 +896,7 @@ static void test_CommandLine(void)
 
     /* the basics */
     get_file_name(resfile);
-    sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\" \"\"\"\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -905,9 +905,10 @@ static void test_CommandLine(void)
     CloseHandle(info.hThread);
     CloseHandle(info.hProcess);
 
-    okChildInt("Arguments", "argcA", 5);
+    okChildInt("Arguments", "argcA", 6);
     okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe");
-    okChildString("Arguments", "argvA5", NULL);
+    okChildString("Arguments", "argvA5", "\"");
+    okChildString("Arguments", "argvA6", NULL);
     okChildString("Arguments", "CommandLineA", buffer);
     release_memory();
     DeleteFileA(resfile);
diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c
index 2ff8610..6c6c427 100644
--- a/dlls/ntdll/process.c
+++ b/dlls/ntdll/process.c
@@ -815,9 +815,13 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
         else if (*s == '\\') bcount++;  /* '\', count them */
         else if ((*s == '"') && ((bcount & 1) == 0))
         {
-            /* unescaped '"' */
-            in_quotes = !in_quotes;
-            bcount = 0;
+            if (in_quotes && s[1] == '"') s++;
+            else
+            {
+                /* unescaped '"' */
+                in_quotes = !in_quotes;
+                bcount = 0;
+            }
         }
         else bcount = 0; /* a regular character */
         s++;
@@ -864,7 +868,12 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
                  */
                 d -= bcount/2;
                 s++;
-                in_quotes = !in_quotes;
+                if (in_quotes && *s == '"')
+                {
+                    *d++ = '"';
+                    s++;
+                }
+                else in_quotes = !in_quotes;
             }
             else
             {




More information about the wine-cvs mailing list