Module: wine Branch: master Commit: 9aff5c88ad874698e07c44bd3825a70414ee77e1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=9aff5c88ad874698e07c44bd38...
Author: Hugh McMaster hugh.mcmaster@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@outlook.com Signed-off-by: Alexandre Julliard julliard@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");