[PATCH] fix command line argument escaping in build_command_line
Jacob Lifshay
programmerjake at gmail.com
Tue Jan 31 17:42:45 CST 2017
fixes bug 40952
Signed-off-by: Jacob Lifshay <programmerjake at gmail.com>
---
dlls/kernel32/process.c | 184 +++++++++++++++++++++++++++---------------------
1 file changed, 104 insertions(+), 80 deletions(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 2130240..060247c 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -745,6 +745,10 @@ static void update_library_argv0( const WCHAR *argv0 )
* resulting in an odd number of '\' followed by a '"'
* '\"' -> '\\\"'
* '\\"' -> '\\\\\"'
+ * - '\'s are followed by the closing '"' must be doubled,
+ * resulting in an even number of '\' followed by a '"'
+ * ' \' -> '" \\"'
+ * ' \\' -> '" \\\\"'
* - '\'s that are not followed by a '"' can be left as is
* 'a\b' == 'a\b'
* 'a\\b' == 'a\\b'
@@ -759,36 +763,46 @@ static BOOL build_command_line( WCHAR **argv )
if (rupp->CommandLine.Buffer) return TRUE; /* already got it from the server */
len = 0;
- for (arg = argv; *arg; arg++)
- {
- BOOL has_space;
- int bcount;
- WCHAR* a;
-
- has_space=FALSE;
- bcount=0;
- a=*arg;
- if( !*a ) has_space=TRUE;
- while (*a!='\0') {
- if (*a=='\\') {
- bcount++;
- } else {
- if (*a==' ' || *a=='\t') {
- has_space=TRUE;
- } else if (*a=='"') {
- /* doubling of '\' preceding a '"',
- * plus escaping of said '"'
- */
- len+=2*bcount+1;
- }
- bcount=0;
+ for(arg = argv; *arg; arg++)
+ {
+ BOOL found_space = FALSE;
+ int slash_count = 0;
+ WCHAR *current_char = *arg;
+ if(arg != argv)
+ len++; /* seperating space */
+ if(!*current_char)
+ {
+ len += 2; /* two quotes */
+ continue;
+ }
+ for(; *current_char; current_char++)
+ {
+ if(*current_char == '\\')
+ {
+ slash_count++;
+ continue;
}
- a++;
+ else if(*current_char == '"')
+ {
+ len += 2 + 2 * slash_count; /* doubling of '\' followed by '\"' */
+ slash_count = 0;
+ continue;
+ }
+ else
+ {
+ len += slash_count;
+ slash_count = 0;
+ }
+ if(*current_char == ' ')
+ found_space = TRUE;
+ len++;
}
- len+=(a-*arg)+1 /* for the separating space */;
- if (has_space)
- len+=2; /* for the quotes */
+ if(found_space)
+ len += 2 + 2 * slash_count; /* doubling of '\' followed by '"' and initial '"' */
+ else
+ len += slash_count;
}
+ len++; /* terminating null */
if (!(rupp->CommandLine.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR))))
return FALSE;
@@ -796,65 +810,75 @@ static BOOL build_command_line( WCHAR **argv )
p = rupp->CommandLine.Buffer;
rupp->CommandLine.Length = (len - 1) * sizeof(WCHAR);
rupp->CommandLine.MaximumLength = len * sizeof(WCHAR);
- for (arg = argv; *arg; arg++)
- {
- BOOL has_space,has_quote;
- WCHAR* a;
-
- /* Check for quotes and spaces in this argument */
- has_space=has_quote=FALSE;
- a=*arg;
- if( !*a ) has_space=TRUE;
- while (*a!='\0') {
- if (*a==' ' || *a=='\t') {
- has_space=TRUE;
- if (has_quote)
- break;
- } else if (*a=='"') {
- has_quote=TRUE;
- if (has_space)
- break;
+ for(arg = argv; *arg; arg++)
+ {
+ BOOL found_space = FALSE;
+ int slash_count = 0;
+ WCHAR *current_char = *arg;
+ if(arg != argv)
+ *p++ = ' '; /* seperating space */
+ if(!*current_char)
+ {
+ *p++ = '"'; /* two quotes */
+ *p++ = '"';
+ continue;
+ }
+ for(; *current_char; current_char++)
+ {
+ if(*current_char == ' ')
+ {
+ found_space = TRUE;
+ break;
}
- a++;
}
-
- /* Now transfer it to the command line */
- if (has_space)
- *p++='"';
- if (has_quote) {
- int bcount;
-
- bcount=0;
- a=*arg;
- while (*a!='\0') {
- if (*a=='\\') {
- *p++=*a;
- bcount++;
- } else {
- if (*a=='"') {
- int i;
-
- /* Double all the '\\' preceding this '"', plus one */
- for (i=0;i<=bcount;i++)
- *p++='\\';
- *p++='"';
- } else {
- *p++=*a;
- }
- bcount=0;
+ if(found_space)
+ *p++ = '"';
+ for(current_char = *arg; *current_char; current_char++)
+ {
+ if(*current_char == '\\')
+ {
+ slash_count++;
+ continue;
+ }
+ else if(*current_char == '"')
+ {
+ /* doubling of '\' followed by '\"' */
+ while(slash_count-- > 0)
+ {
+ *p++ = '\\';
+ *p++ = '\\';
}
- a++;
+ *p++ = '\\';
+ *p++ = '"';
+ slash_count = 0;
+ continue;
}
- } else {
- WCHAR* x = *arg;
- while ((*p=*x++)) p++;
+ else
+ {
+ while(slash_count-- > 0)
+ *p++ = '\\';
+ slash_count = 0;
+ }
+ if(*current_char == ' ')
+ found_space = TRUE;
+ *p++ = *current_char;
+ }
+ if(found_space)
+ {
+ /* doubling of '\' followed by '"' and initial '"' */
+ while(slash_count-- > 0)
+ {
+ *p++ = '\\';
+ *p++ = '\\';
+ }
+ *p++ = '"';
+ }
+ else
+ {
+ while(slash_count-- > 0)
+ *p++ = '\\';
}
- if (has_space)
- *p++='"';
- *p++=' ';
}
- if (p > rupp->CommandLine.Buffer)
- p--; /* remove last space */
*p = '\0';
return TRUE;
--
2.7.4
More information about the wine-patches
mailing list