Eric Pouech : winedbg: Properly escape debuggee arguments.

Alexandre Julliard julliard at winehq.org
Wed Dec 1 15:23:51 CST 2021


Module: wine
Branch: master
Commit: 94ca4be2a62cdb05adaee524084875b04b283afb
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=94ca4be2a62cdb05adaee524084875b04b283afb

Author: Eric Pouech <eric.pouech at gmail.com>
Date:   Wed Dec  1 15:30:17 2021 +0100

winedbg: Properly escape debuggee arguments.

Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/winedbg/tgt_active.c | 106 +++++++++++++++++++++++++++++++++---------
 1 file changed, 85 insertions(+), 21 deletions(-)

diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index 2a2af67debe..4bcd5ba659e 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -636,6 +636,88 @@ static BOOL dbg_start_debuggee(LPSTR cmdLine)
     return TRUE;
 }
 
+/***********************************************************************
+ *           dbg_build_command_line
+ *
+ * (converted from dlls/ntdll/unix/env.c)
+ *
+ * Build the command line of a process from the argv array.
+ *
+ * We must quote and escape characters so that the argv array can be rebuilt
+ * from the command line:
+ * - spaces and tabs must be quoted
+ *   'a b'   -> '"a b"'
+ * - quotes must be escaped
+ *   '"'     -> '\"'
+ * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
+ *   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'
+ */
+static char *dbg_build_command_line( char **argv )
+{
+    int len;
+    char **arg, *ret;
+    LPSTR p;
+
+    len = 1;
+    for (arg = argv; *arg; arg++) len += 3 + 2 * strlen( *arg );
+    if (!(ret = malloc( len ))) return NULL;
+
+    p = ret;
+    for (arg = argv; *arg; arg++)
+    {
+        BOOL has_space, has_quote;
+        int i, bcount;
+        char *a;
+
+        /* check for quotes and spaces in this argument (first arg is always quoted) */
+        has_space = (arg == argv) || !**arg || strchr( *arg, ' ' ) || strchr( *arg, '\t' );
+        has_quote = strchr( *arg, '"' ) != NULL;
+
+        /* now transfer it to the command line */
+        if (has_space) *p++ = '"';
+        if (has_quote || has_space)
+        {
+            bcount = 0;
+            for (a = *arg; *a; a++)
+            {
+                if (*a == '\\') bcount++;
+                else
+                {
+                    if (*a == '"') /* double all the '\\' preceding this '"', plus one */
+                        for (i = 0; i <= bcount; i++) *p++ = '\\';
+                    bcount = 0;
+                }
+                *p++ = *a;
+            }
+        }
+        else
+        {
+            strcpy( p, *arg );
+            p += strlen( p );
+        }
+        if (has_space)
+        {
+            /* Double all the '\' preceding the closing quote */
+            for (i = 0; i < bcount; i++) *p++ = '\\';
+            *p++ = '"';
+        }
+        *p++ = ' ';
+    }
+    if (p > ret) p--;  /* remove last space */
+    *p = 0;
+    return ret;
+}
+
+
 void	dbg_run_debuggee(const char* args)
 {
     if (args)
@@ -807,35 +889,17 @@ enum dbg_start  dbg_active_attach(int argc, char* argv[])
  */
 enum dbg_start    dbg_active_launch(int argc, char* argv[])
 {
-    int         i, len;
     LPSTR	cmd_line;
 
     if (argc == 0) return start_error_parse;
 
-    if (!(cmd_line = HeapAlloc(GetProcessHeap(), 0, len = 1)))
-    {
-    oom_leave:
-        dbg_printf("Out of memory\n");
-        return start_error_init;
-    }
-    cmd_line[0] = '\0';
-
-    for (i = 0; i < argc; i++)
-    {
-        len += strlen(argv[i]) + 1;
-        if (!(cmd_line = HeapReAlloc(GetProcessHeap(), 0, cmd_line, len)))
-            goto oom_leave;
-        strcat(cmd_line, argv[i]);
-        cmd_line[len - 2] = ' ';
-        cmd_line[len - 1] = '\0';
-    }
-
+    cmd_line = dbg_build_command_line(argv);
     if (!dbg_start_debuggee(cmd_line))
     {
-        HeapFree(GetProcessHeap(), 0, cmd_line);
+        free(cmd_line);
         return start_error_init;
     }
-    HeapFree(GetProcessHeap(), 0, dbg_last_cmd_line);
+    free(dbg_last_cmd_line);
     dbg_last_cmd_line = cmd_line;
     return start_ok;
 }




More information about the wine-cvs mailing list