Commit 032d32f9 authored by Hugh McMaster's avatar Hugh McMaster Committed by Alexandre Julliard

regedit: Improve the parsing of multiline hex data during the registry import operation.

parent c750c2a9
...@@ -147,6 +147,8 @@ enum parser_state ...@@ -147,6 +147,8 @@ enum parser_state
STRING_DATA, /* parsing REG_SZ data */ STRING_DATA, /* parsing REG_SZ data */
DWORD_DATA, /* parsing DWORD data */ DWORD_DATA, /* parsing DWORD data */
HEX_DATA, /* parsing REG_BINARY, REG_NONE, REG_EXPAND_SZ or REG_MULTI_SZ data */ HEX_DATA, /* parsing REG_BINARY, REG_NONE, REG_EXPAND_SZ or REG_MULTI_SZ data */
EOL_BACKSLASH, /* preparing to parse multiple lines of hex data */
HEX_MULTILINE, /* parsing multiple lines of hex data */
UNKNOWN_DATA, /* parsing an unhandled or invalid data type */ UNKNOWN_DATA, /* parsing an unhandled or invalid data type */
SET_VALUE, /* adding a value to the registry */ SET_VALUE, /* adding a value to the registry */
NB_PARSER_STATES NB_PARSER_STATES
...@@ -165,6 +167,7 @@ struct parser ...@@ -165,6 +167,7 @@ struct parser
DWORD data_type; /* data type */ DWORD data_type; /* data type */
void *data; /* value data */ void *data; /* value data */
DWORD data_size; /* size of the data (in bytes) */ DWORD data_size; /* size of the data (in bytes) */
BOOL backslash; /* TRUE if the current line contains a backslash */
enum parser_state state; /* current parser state */ enum parser_state state; /* current parser state */
}; };
...@@ -184,6 +187,8 @@ static WCHAR *data_type_state(struct parser *parser, WCHAR *pos); ...@@ -184,6 +187,8 @@ static WCHAR *data_type_state(struct parser *parser, WCHAR *pos);
static WCHAR *string_data_state(struct parser *parser, WCHAR *pos); static WCHAR *string_data_state(struct parser *parser, WCHAR *pos);
static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos); static WCHAR *dword_data_state(struct parser *parser, WCHAR *pos);
static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos); static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos);
static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos);
static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos);
static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos); static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos);
static WCHAR *set_value_state(struct parser *parser, WCHAR *pos); static WCHAR *set_value_state(struct parser *parser, WCHAR *pos);
...@@ -202,6 +207,8 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] = ...@@ -202,6 +207,8 @@ static const parser_state_func parser_funcs[NB_PARSER_STATES] =
string_data_state, /* STRING_DATA */ string_data_state, /* STRING_DATA */
dword_data_state, /* DWORD_DATA */ dword_data_state, /* DWORD_DATA */
hex_data_state, /* HEX_DATA */ hex_data_state, /* HEX_DATA */
eol_backslash_state, /* EOL_BACKSLASH */
hex_multiline_state, /* HEX_MULTILINE */
unknown_data_state, /* UNKNOWN_DATA */ unknown_data_state, /* UNKNOWN_DATA */
set_value_state, /* SET_VALUE */ set_value_state, /* SET_VALUE */
}; };
...@@ -214,6 +221,19 @@ static inline enum parser_state set_state(struct parser *parser, enum parser_sta ...@@ -214,6 +221,19 @@ static inline enum parser_state set_state(struct parser *parser, enum parser_sta
return ret; return ret;
} }
static void *resize_buffer(void *buf, size_t count)
{
void *new_buf;
if (buf)
new_buf = HeapReAlloc(GetProcessHeap(), 0, buf, count);
else
new_buf = HeapAlloc(GetProcessHeap(), 0, count);
CHECK_ENOUGH_MEMORY(new_buf);
return new_buf;
}
/****************************************************************************** /******************************************************************************
* Converts a hex representation of a DWORD into a DWORD. * Converts a hex representation of a DWORD into a DWORD.
*/ */
...@@ -246,37 +266,61 @@ error: ...@@ -246,37 +266,61 @@ error:
} }
/****************************************************************************** /******************************************************************************
* Converts comma-separated hex data into a binary string. * Converts comma-separated hex data into a binary string and modifies
* the input parameter to skip the concatenating backslash, if found.
*
* Returns TRUE or FALSE to indicate whether parsing was successful.
*/ */
static BYTE *convert_hex_csv_to_hex(WCHAR *str, DWORD *size) static BOOL convert_hex_csv_to_hex(struct parser *parser, WCHAR **str)
{ {
size_t size;
BYTE *d;
WCHAR *s; WCHAR *s;
BYTE *d, *data;
parser->backslash = FALSE;
/* The worst case is 1 digit + 1 comma per byte */ /* The worst case is 1 digit + 1 comma per byte */
*size=(lstrlenW(str)+1)/2; size = ((lstrlenW(*str) + 1) / 2) + parser->data_size;
data=HeapAlloc(GetProcessHeap(), 0, *size); parser->data = resize_buffer(parser->data, size);
CHECK_ENOUGH_MEMORY(data);
s = *str;
s = str; d = (BYTE *)parser->data + parser->data_size;
d = data;
*size=0; while (*s)
while (*s != '\0') { {
UINT wc;
WCHAR *end; WCHAR *end;
unsigned long wc;
wc = strtoulW(s, &end, 16);
if (wc > 0xff) return FALSE;
if (s == end && wc == 0)
{
while (*end == ' ' || *end == '\t') end++;
if (*end == '\\')
{
parser->backslash = TRUE;
*str = end + 1;
return TRUE;
}
return FALSE;
}
wc = strtoulW(s,&end,16); *d++ = wc;
if (end == s || wc > 0xff || (*end && *end != ',')) { parser->data_size++;
HeapFree(GetProcessHeap(), 0, data);
return NULL; if (*end && *end != ',')
{
while (*end == ' ' || *end == '\t') end++;
if (*end && *end != ';') return FALSE;
return TRUE;
} }
*d++ =(BYTE)wc;
(*size)++;
if (*end) end++; if (*end) end++;
s = end; s = end;
} }
return data; return TRUE;
} }
/****************************************************************************** /******************************************************************************
...@@ -790,9 +834,15 @@ static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos) ...@@ -790,9 +834,15 @@ static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos)
{ {
WCHAR *line = pos; WCHAR *line = pos;
if (!(parser->data = convert_hex_csv_to_hex(line, &parser->data_size))) if (!convert_hex_csv_to_hex(parser, &line))
goto invalid; goto invalid;
if (parser->backslash)
{
set_state(parser, EOL_BACKSLASH);
return line;
}
if (!parser->is_unicode && (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ)) if (!parser->is_unicode && (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ))
{ {
void *tmp = parser->data; void *tmp = parser->data;
...@@ -814,6 +864,44 @@ invalid: ...@@ -814,6 +864,44 @@ invalid:
return line; return line;
} }
/* handler for parser EOL_BACKSLASH state */
static WCHAR *eol_backslash_state(struct parser *parser, WCHAR *pos)
{
WCHAR *p = pos;
while (*p == ' ' || *p == '\t') p++;
if (*p && *p != ';') goto invalid;
set_state(parser, HEX_MULTILINE);
return pos;
invalid:
HeapFree(GetProcessHeap(), 0, parser->data);
parser->data = NULL;
parser->data_size = 0;
set_state(parser, LINE_START);
return p;
}
/* handler for parser HEX_MULTILINE state */
static WCHAR *hex_multiline_state(struct parser *parser, WCHAR *pos)
{
WCHAR *line;
if (!(line = get_line(parser->file)))
{
set_state(parser, SET_VALUE);
return pos;
}
while (*line == ' ' || *line == '\t') line++;
if (*line == ';') return line;
set_state(parser, HEX_DATA);
return line;
}
/* handler for parser UNKNOWN_DATA state */ /* handler for parser UNKNOWN_DATA state */
static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos) static WCHAR *unknown_data_state(struct parser *parser, WCHAR *pos)
{ {
...@@ -893,13 +981,6 @@ static WCHAR *get_lineA(FILE *fp) ...@@ -893,13 +981,6 @@ static WCHAR *get_lineA(FILE *fp)
next = p + 1; next = p + 1;
if (*p == '\r' && *(p + 1) == '\n') next++; if (*p == '\r' && *(p + 1) == '\n') next++;
*p = 0; *p = 0;
if (p > buf && *(p - 1) == '\\')
{
while (*next == ' ' || *next == '\t') next++;
memmove(p - 1, next, strlen(next) + 1);
next = line;
continue;
}
if (*line == ';' || *line == '#') if (*line == ';' || *line == '#')
{ {
line = next; line = next;
...@@ -963,13 +1044,6 @@ static WCHAR *get_lineW(FILE *fp) ...@@ -963,13 +1044,6 @@ static WCHAR *get_lineW(FILE *fp)
next = p + 1; next = p + 1;
if (*p == '\r' && *(p + 1) == '\n') next++; if (*p == '\r' && *(p + 1) == '\n') next++;
*p = 0; *p = 0;
if (p > buf && *(p - 1) == '\\')
{
while (*next == ' ' || *next == '\t') next++;
memmove(p - 1, next, (strlenW(next) + 1) * sizeof(WCHAR));
next = line;
continue;
}
if (*line == ';' || *line == '#') if (*line == ';' || *line == '#')
{ {
line = next; line = next;
...@@ -1473,6 +1547,7 @@ BOOL import_registry_file(FILE *reg_file) ...@@ -1473,6 +1547,7 @@ BOOL import_registry_file(FILE *reg_file)
parser.data_type = 0; parser.data_type = 0;
parser.data = NULL; parser.data = NULL;
parser.data_size = 0; parser.data_size = 0;
parser.backslash = FALSE;
parser.state = HEADER; parser.state = HEADER;
pos = parser.two_wchars; pos = parser.two_wchars;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment