From 87917df887e00254a457a859c06892307b4e2daf Mon Sep 17 00:00:00 2001 From: Brendan McGrath Date: Tue, 26 Feb 2019 19:39:25 +1100 Subject: [PATCH] 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 Signed-off-by: Alexandre Julliard --- 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 ad257a054e4..89b561ef811 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -1505,9 +1505,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; @@ -1551,7 +1555,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 fe68d28e914..f62f8fb0ba1 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 2ff8610ccee..6c6c4273729 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 {