diff --git a/winpr/libwinpr/registry/registry_reg.c b/winpr/libwinpr/registry/registry_reg.c index 2a03e4e59..8b833085e 100644 --- a/winpr/libwinpr/registry/registry_reg.c +++ b/winpr/libwinpr/registry/registry_reg.c @@ -53,21 +53,40 @@ static struct reg_data_type REG_DATA_TYPE_TABLE[] = { { "\"", 1, REG_SZ }, { "hex:", 4, REG_BINARY }, { "hex(2):\"", 8, REG_EXPAND_SZ }, { "hex(7):\"", 8, REG_MULTI_SZ }, - { "hex(b):\"", 8, REG_QWORD }, - { NULL, 0, 0 } }; + { "hex(b):\"", 8, REG_QWORD } }; -static char* REG_DATA_TYPE_STRINGS[] = { "REG_NONE", - "REG_SZ", - "REG_EXPAND_SZ", - "REG_BINARY", - "REG_DWORD", - "REG_DWORD_BIG_ENDIAN", - "REG_LINK", - "REG_MULTI_SZ", - "REG_RESOURCE_LIST", - "REG_FULL_RESOURCE_DESCRIPTOR", - "REG_RESOURCE_REQUIREMENTS_LIST", - "REG_QWORD" }; +static char* reg_data_type_string(DWORD type) +{ + switch (type) + { + case REG_NONE: + return "REG_NONE"; + case REG_SZ: + return "REG_SZ"; + case REG_EXPAND_SZ: + return "REG_EXPAND_SZ"; + case REG_BINARY: + return "REG_BINARY"; + case REG_DWORD: + return "REG_DWORD"; + case REG_DWORD_BIG_ENDIAN: + return "REG_DWORD_BIG_ENDIAN"; + case REG_LINK: + return "REG_LINK"; + case REG_MULTI_SZ: + return "REG_MULTI_SZ"; + case REG_RESOURCE_LIST: + return "REG_RESOURCE_LIST"; + case REG_FULL_RESOURCE_DESCRIPTOR: + return "REG_FULL_RESOURCE_DESCRIPTOR"; + case REG_RESOURCE_REQUIREMENTS_LIST: + return "REG_RESOURCE_REQUIREMENTS_LIST"; + case REG_QWORD: + return "REG_QWORD"; + default: + return "REG_UNKNOWN"; + } +} static void reg_load_start(Reg* reg) { @@ -115,14 +134,16 @@ static void reg_load_finish(Reg* reg) static RegVal* reg_load_value(Reg* reg, RegKey* key) { int index; - char* p[5]; + char* p[5] = { 0 }; size_t length; - char* name; + char* name = NULL; char* type; char* data; - RegVal* value; + RegVal* value = NULL; + WINPR_ASSERT(reg); WINPR_ASSERT(key); + p[0] = reg->line + 1; p[1] = strstr(p[0], "\"="); p[2] = p[1] + 2; @@ -135,65 +156,81 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key) data = p[3] + 1; length = p[1] - p[0]; - name = (char*)malloc(length + 1); + if (length < 1) + goto fail; + + name = (char*)calloc(length + 1, sizeof(char)); if (!name) - return NULL; + goto fail; memcpy(name, p[0], length); - name[length] = '\0'; - value = (RegVal*)malloc(sizeof(RegVal)); + value = (RegVal*)calloc(1, sizeof(RegVal)); if (!value) - { - free(name); - return NULL; - } + goto fail; value->name = name; value->type = REG_NONE; value->next = value->prev = NULL; - for (index = 0; REG_DATA_TYPE_TABLE[index].length > 0; index++) + for (index = 0; index < ARRAYSIZE(REG_DATA_TYPE_TABLE); index++) { - if (strncmp(type, REG_DATA_TYPE_TABLE[index].tag, REG_DATA_TYPE_TABLE[index].length) == 0) + const struct reg_data_type* current = ®_DATA_TYPE_TABLE[index]; + WINPR_ASSERT(current->tag); + WINPR_ASSERT(current->length > 0); + WINPR_ASSERT(current->type != REG_NONE); + + if (strncmp(type, current->tag, current->length) == 0) { - value->type = REG_DATA_TYPE_TABLE[index].type; + value->type = current->type; break; } } - if (value->type == REG_DWORD) + switch (value->type) { - unsigned long val; - errno = 0; - val = strtoul(data, NULL, 16); - - if ((errno != 0) || (val > UINT32_MAX)) + case REG_DWORD: { - free(value); - free(name); - return NULL; + unsigned long val; + errno = 0; + val = strtoul(data, NULL, 16); + + if ((errno != 0) || (val > UINT32_MAX)) + goto fail; + + value->data.dword = (DWORD)val; } - - value->data.dword = val; - } - else if (value->type == REG_SZ) - { - p[4] = strchr(data, '"'); - p[4][0] = '\0'; - value->data.string = _strdup(data); - - if (!value->data.string) + break; + case REG_SZ: { - free(value); - free(name); - return NULL; + size_t len, cmp; + char* end; + char* start = strchr(data, '"'); + if (!start) + goto fail; + + /* Check for terminating quote, check it is the last symbol */ + len = strlen(start); + end = strchr(start + 1, '"'); + if (!end) + goto fail; + cmp = end - start + 1; + if (len != cmp) + goto fail; + if (start[0] == '"') + start++; + if (end[0] == '"') + end[0] = '\0'; + value->data.string = _strdup(start); + + if (!value->data.string) + goto fail; } - } - else - { - WLog_ERR(TAG, "unimplemented format: %s", REG_DATA_TYPE_STRINGS[value->type]); + break; + default: + WLog_ERR(TAG, "unimplemented format: %s", reg_data_type_string(value->type)); + break; } if (!key->values) @@ -214,6 +251,11 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key) } return value; + +fail: + free(value); + free(name); + return NULL; } static BOOL reg_load_has_next_line(Reg* reg) @@ -375,7 +417,7 @@ static void reg_unload_value(Reg* reg, RegVal* value) } else { - WLog_ERR(TAG, "unimplemented format: %s", REG_DATA_TYPE_STRINGS[value->type]); + WLog_ERR(TAG, "unimplemented format: %s", reg_data_type_string(value->type)); } free(value);