Hugh McMaster : regedit: Validate REG_SZ import data before processing it any further.

Alexandre Julliard julliard at winehq.org
Tue Apr 25 16:22:36 CDT 2017


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

Author: Hugh McMaster <hugh.mcmaster at outlook.com>
Date:   Tue Apr 25 13:31:10 2017 +0000

regedit: Validate REG_SZ import data before processing it any further.

Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/regedit/regproc.c       | 30 ++++++++++++++++++++++--------
 programs/regedit/tests/regedit.c | 14 +++++++-------
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index 1672f22..22c4d9e 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -264,13 +264,19 @@ static DWORD getDataType(LPWSTR *lpValue, DWORD* parse_type)
 }
 
 /******************************************************************************
- * Replaces escape sequences with the characters.
+ * Replaces escape sequences with their character equivalents and
+ * null-terminates the string on the first non-escaped double quote.
+ *
+ * Assigns a pointer to the remaining unparsed data in the line.
+ * Returns TRUE or FALSE to indicate whether a closing double quote was found.
  */
-static int REGPROC_unescape_string(WCHAR* str)
+static BOOL REGPROC_unescape_string(WCHAR *str, WCHAR **unparsed)
 {
     int str_idx = 0;            /* current character under analysis */
     int val_idx = 0;            /* the last character of the unescaped string */
     int len = lstrlenW(str);
+    BOOL ret;
+
     for (str_idx = 0; str_idx < len; str_idx++, val_idx++) {
         if (str[str_idx] == '\\') {
             str_idx++;
@@ -293,12 +299,17 @@ static int REGPROC_unescape_string(WCHAR* str)
                 str[val_idx] = str[str_idx];
                 break;
             }
+        } else if (str[str_idx] == '"') {
+            break;
         } else {
             str[val_idx] = str[str_idx];
         }
     }
+
+    ret = (str[str_idx] == '"');
+    *unparsed = str + str_idx + 1;
     str[val_idx] = '\0';
-    return val_idx;
+    return ret;
 }
 
 static HKEY parseKeyName(LPWSTR lpKeyName, LPWSTR *lpKeyPath)
@@ -397,12 +408,14 @@ static LONG setValue(WCHAR* val_name, WCHAR* val_data, BOOL is_unicode)
 
     if (dwParseType == REG_SZ)          /* no conversion for string */
     {
-        dwLen = REGPROC_unescape_string(val_data);
-        if(!dwLen || val_data[dwLen-1] != '"')
+        WCHAR *line;
+        if (!REGPROC_unescape_string(val_data, &line))
+            return ERROR_INVALID_DATA;
+        while (*line == ' ' || *line == '\t') line++;
+        if (*line && *line != ';')
             return ERROR_INVALID_DATA;
-        val_data[dwLen-1] = '\0'; /* remove last quotes */
         lpbData = (BYTE*) val_data;
-        dwLen = dwLen * sizeof(WCHAR); /* size is in bytes */
+        dwLen = (lstrlenW(val_data) + 1) * sizeof(WCHAR); /* size is in bytes */
     }
     else if (dwParseType == REG_DWORD)  /* Convert the dword types */
     {
@@ -520,6 +533,7 @@ static void processSetValue(WCHAR* line, BOOL is_unicode)
 {
     WCHAR* val_name;                   /* registry value name   */
     WCHAR* val_data;                   /* registry value data   */
+    WCHAR* p;
     int line_idx = 0;                 /* current character under analysis */
     LONG res;
 
@@ -570,7 +584,7 @@ static void processSetValue(WCHAR* line, BOOL is_unicode)
     while (line_idx > 0 && isspaceW(val_data[line_idx-1])) line_idx--;
     val_data[line_idx] = '\0';
 
-    REGPROC_unescape_string(val_name);
+    REGPROC_unescape_string(val_name, &p);
     res = setValue(val_name, val_data, is_unicode);
     if ( res != ERROR_SUCCESS )
         output_message(STRING_SETVALUE_FAILED, val_name, currentKeyName);
diff --git a/programs/regedit/tests/regedit.c b/programs/regedit/tests/regedit.c
index 7584ed4..8010a47 100644
--- a/programs/regedit/tests/regedit.c
+++ b/programs/regedit/tests/regedit.c
@@ -560,8 +560,8 @@ static void test_invalid_import(void)
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
                     "\"Test15a\"=\"foo\"bar\"\n"
                     "\"Test15b\"=\"foo\"\"bar\"\n\n");
-    todo_wine verify_reg_nonexist(hkey, "Test15a");
-    todo_wine verify_reg_nonexist(hkey, "Test15b");
+    verify_reg_nonexist(hkey, "Test15a");
+    verify_reg_nonexist(hkey, "Test15b");
 
     exec_import_str("REGEDIT4\n\n"
                     "[HKEY_CURRENT_USER\\" KEY_BASE "]\n"
@@ -607,7 +607,7 @@ static void test_comments(void)
                     "\"Wine5\"=dword:01020304 #comment\n"
                     "\"Wine6\"=dword:02040608 ;comment\n\n");
     verify_reg_nonexist(hkey, "Wine3");
-    todo_wine verify_reg(hkey, "Wine4", REG_SZ, "Value 2", 8, 0);
+    verify_reg(hkey, "Wine4", REG_SZ, "Value 2", 8, 0);
     verify_reg_nonexist(hkey, "Wine5");
     dword = 0x2040608;
     verify_reg(hkey, "Wine6", REG_DWORD, &dword, sizeof(dword), 0);
@@ -639,9 +639,9 @@ static void test_comments(void)
     verify_reg_nonexist(hkey, "Comment2");
     verify_reg_nonexist(hkey, "Comment3");
     verify_reg_nonexist(hkey, "Comment4");
-    todo_wine verify_reg_nonexist(hkey, "Wine11");
+    verify_reg_nonexist(hkey, "Wine11");
     verify_reg_nonexist(hkey, "Comment5");
-    verify_reg(hkey, "Wine12", REG_SZ, "Value 7", 8, TODO_REG_SIZE|TODO_REG_DATA);
+    verify_reg(hkey, "Wine12", REG_SZ, "Value 7", 8, 0);
     verify_reg_nonexist(hkey, "Comment6");
 
     exec_import_str("REGEDIT4\n\n"
@@ -690,8 +690,8 @@ static void test_comments(void)
                     "\"Wine26b\"=\"Value2\"\t\t;comment\n"
                     "\"Wine26c\"=\"Value3\"  #comment\n"
                     "\"Wine26d\"=\"Value4\"\t\t#comment\n\n");
-    todo_wine verify_reg(hkey, "Wine26a", REG_SZ, "Value1", 7, 0);
-    todo_wine verify_reg(hkey, "Wine26b", REG_SZ, "Value2", 7, 0);
+    verify_reg(hkey, "Wine26a", REG_SZ, "Value1", 7, 0);
+    verify_reg(hkey, "Wine26b", REG_SZ, "Value2", 7, 0);
     verify_reg_nonexist(hkey, "Wine26c");
     verify_reg_nonexist(hkey, "Wine26d");
 




More information about the wine-cvs mailing list