D-Bus: Fix string array dict entry parser in out-of-memory case

entry->strarray_value was left to point to freed memory in case
os_realloc_array() failed. This resulted in the following
wpa_dbus_dict_entry_clear() trying to free an already freed memory area.
In addition, the separately allocated strings in the array would have
been leaked in such a case. Furthermore, wpa_dbus_dict_entry_clear() was
not prepared for the possibility of the initial os_calloc() call failing
and entry->strarray_value being NULL without array_len being cleared to
zero. That would have resulted in reading uninitialized memory and NULL
pointer dereference.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2015-01-06 17:04:24 +02:00
parent c61bc23aa2
commit f2d57282ad

View file

@ -748,18 +748,16 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
struct wpa_dbus_dict_entry *entry) struct wpa_dbus_dict_entry *entry)
{ {
dbus_uint32_t count = 0; dbus_uint32_t count = 0;
dbus_bool_t success = FALSE;
char **buffer, **nbuffer; char **buffer, **nbuffer;
entry->strarray_value = NULL; entry->strarray_value = NULL;
entry->array_len = 0;
entry->array_type = DBUS_TYPE_STRING; entry->array_type = DBUS_TYPE_STRING;
buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE); buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
if (buffer == NULL) if (buffer == NULL)
return FALSE; return FALSE;
entry->strarray_value = buffer;
entry->array_len = 0;
while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) { while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
const char *value; const char *value;
char *str; char *str;
@ -769,15 +767,13 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
buffer, count + STR_ARRAY_CHUNK_SIZE, buffer, count + STR_ARRAY_CHUNK_SIZE,
STR_ARRAY_ITEM_SIZE); STR_ARRAY_ITEM_SIZE);
if (nbuffer == NULL) { if (nbuffer == NULL) {
os_free(buffer);
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"dbus: %s out of memory trying to retrieve the string array", "dbus: %s out of memory trying to retrieve the string array",
__func__); __func__);
goto done; goto fail;
} }
buffer = nbuffer; buffer = nbuffer;
} }
entry->strarray_value = buffer;
dbus_message_iter_get_basic(iter, &value); dbus_message_iter_get_basic(iter, &value);
wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s", wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s",
@ -787,12 +783,13 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"dbus: %s out of memory trying to duplicate the string array", "dbus: %s out of memory trying to duplicate the string array",
__func__); __func__);
goto done; goto fail;
} }
entry->strarray_value[count] = str; buffer[count++] = str;
entry->array_len = ++count;
dbus_message_iter_next(iter); dbus_message_iter_next(iter);
} }
entry->strarray_value = buffer;
entry->array_len = count;
wpa_printf(MSG_MSGDUMP, "%s: string_array length %u", wpa_printf(MSG_MSGDUMP, "%s: string_array length %u",
__func__, entry->array_len); __func__, entry->array_len);
@ -802,10 +799,15 @@ static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
entry->strarray_value = NULL; entry->strarray_value = NULL;
} }
success = TRUE; return TRUE;
done: fail:
return success; while (count > 0) {
count--;
os_free(buffer[count]);
}
os_free(buffer);
return FALSE;
} }
@ -1114,6 +1116,8 @@ void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
os_free(entry->bytearray_value); os_free(entry->bytearray_value);
break; break;
case DBUS_TYPE_STRING: case DBUS_TYPE_STRING:
if (!entry->strarray_value)
break;
for (i = 0; i < entry->array_len; i++) for (i = 0; i < entry->array_len; i++)
os_free(entry->strarray_value[i]); os_free(entry->strarray_value[i]);
os_free(entry->strarray_value); os_free(entry->strarray_value);