Hans Leidekker : msiexec: Fix parsing of command lines where quoted strings and properties are not separated by whitespace.

Alexandre Julliard julliard at winehq.org
Tue Jun 6 15:23:28 CDT 2017


Module: wine
Branch: master
Commit: d73c38fe9ab18900eb7f1e1a30570a3139501466
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d73c38fe9ab18900eb7f1e1a30570a3139501466

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Jun  6 09:20:16 2017 +0200

msiexec: Fix parsing of command lines where quoted strings and properties are not separated by whitespace.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/msiexec/msiexec.c | 169 +++++++++++++++++++++++----------------------
 1 file changed, 87 insertions(+), 82 deletions(-)

diff --git a/programs/msiexec/msiexec.c b/programs/msiexec/msiexec.c
index b7999d1..8dcd216 100644
--- a/programs/msiexec/msiexec.c
+++ b/programs/msiexec/msiexec.c
@@ -216,14 +216,6 @@ static DWORD msi_atou(LPCWSTR str)
 	return ret;
 }
 
-static LPWSTR msi_strdup(LPCWSTR str)
-{
-	DWORD len = lstrlenW(str)+1;
-	LPWSTR ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
-	lstrcpyW(ret, str);
-	return ret;
-}
-
 /* str1 is the same as str2, ignoring case */
 static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2)
 {
@@ -413,90 +405,103 @@ static INT DoEmbedding( LPWSTR key )
 
 enum chomp_state
 {
-	cs_whitespace,
-	cs_token,
-	cs_quote
+    CS_WHITESPACE,
+    CS_TOKEN,
+    CS_QUOTE
 };
 
-static int chomp( WCHAR *str )
+static int chomp( const WCHAR *in, WCHAR *out )
 {
-	enum chomp_state state = cs_token;
-	WCHAR *p, *out;
-        int count = 1;
-        BOOL ignore;
-
-	for( p = str, out = str; *p; p++ )
-	{
-                ignore = TRUE;
-		switch( state )
-		{
-		case cs_whitespace:
-			switch( *p )
-			{
-			case ' ':
-				break;
-			case '"':
-				state = cs_quote;
-				count++;
-				break;
-			default:
-				count++;
-                                ignore = FALSE;
-				state = cs_token;
-			}
-			break;
-
-		case cs_token:
-			switch( *p )
-			{
-			case '"':
-				state = cs_quote;
-				break;
-			case ' ':
-				state = cs_whitespace;
-				*out++ = 0;
-				break;
-			default:
-                                ignore = FALSE;
-			}
-			break;
-
-		case cs_quote:
-			switch( *p )
-			{
-			case '"':
-				state = cs_token;
-				break;
-			default:
-                                ignore = FALSE;
-			}
-			break;
-		}
-		if( !ignore )
-			*out++ = *p;
-	}
-
-	*out = 0;
+    enum chomp_state state = CS_TOKEN;
+    const WCHAR *p;
+    int count = 1;
+    BOOL ignore;
 
-	return count;
+    for (p = in; *p; p++)
+    {
+        ignore = TRUE;
+        switch (state)
+        {
+        case CS_WHITESPACE:
+            switch (*p)
+            {
+            case ' ':
+                break;
+            case '"':
+                state = CS_QUOTE;
+                count++;
+                break;
+            default:
+                count++;
+                ignore = FALSE;
+                state = CS_TOKEN;
+            }
+            break;
+
+        case CS_TOKEN:
+            switch (*p)
+            {
+            case '"':
+                state = CS_QUOTE;
+                break;
+            case ' ':
+                state = CS_WHITESPACE;
+                if (out) *out++ = 0;
+                break;
+            default:
+                if (p > in && p[-1] == '"')
+                {
+                    if (out) *out++ = 0;
+                    count++;
+                }
+                ignore = FALSE;
+            }
+            break;
+
+        case CS_QUOTE:
+            switch (*p)
+            {
+            case '"':
+                state = CS_TOKEN;
+                break;
+            default:
+                ignore = FALSE;
+            }
+            break;
+        }
+        if (!ignore && out) *out++ = *p;
+    }
+    if (out) *out = 0;
+    return count;
 }
 
 static void process_args( WCHAR *cmdline, int *pargc, WCHAR ***pargv )
 {
-	WCHAR **argv, *p = msi_strdup(cmdline);
-	int i, n;
+    WCHAR **argv, *p;
+    int i, count;
 
-	n = chomp( p );
-	argv = HeapAlloc(GetProcessHeap(), 0, sizeof (WCHAR*)*(n+1));
-	for( i=0; i<n; i++ )
-	{
-		argv[i] = p;
-		p += lstrlenW(p) + 1;
-	}
-	argv[i] = NULL;
+    *pargc = 0;
+    *pargv = NULL;
+
+    count = chomp( cmdline, NULL );
+    if (!(p = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + count + 1) * sizeof(WCHAR) )))
+        return;
+
+    count = chomp( cmdline, p );
+    if (!(argv = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(WCHAR *) )))
+    {
+        HeapFree( GetProcessHeap(), 0, p );
+        return;
+    }
+    for (i = 0; i < count; i++)
+    {
+        argv[i] = p;
+        p += lstrlenW( p ) + 1;
+    }
+    argv[i] = NULL;
 
-	*pargc = n;
-	*pargv = argv;
+    *pargc = count;
+    *pargv = argv;
 }
 
 static BOOL process_args_from_reg( const WCHAR *ident, int *pargc, WCHAR ***pargv )




More information about the wine-cvs mailing list