base: Fix use-after-free in heim_path_vcreate()
This commit is contained in:
@@ -918,14 +918,14 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
|
|||||||
heim_abort("heim_path_vcreate() does not create root nodes");
|
heim_abort("heim_path_vcreate() does not create root nodes");
|
||||||
|
|
||||||
while (path_element != NULL) {
|
while (path_element != NULL) {
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
next_path_element = va_arg(ap, heim_object_t);
|
next_path_element = va_arg(ap, heim_object_t);
|
||||||
node_type = heim_get_tid(node);
|
node_type = heim_get_tid(node);
|
||||||
|
|
||||||
if (node_type == HEIM_TID_DICT) {
|
if (node_type == HEIM_TID_DICT) {
|
||||||
next_node = heim_dict_get_value(node, path_element);
|
next_node = heim_dict_get_value(node, path_element);
|
||||||
} else if (node_type == HEIM_TID_ARRAY) {
|
} else if (node_type == HEIM_TID_ARRAY) {
|
||||||
int idx = -1;
|
|
||||||
|
|
||||||
if (heim_get_tid(path_element) == HEIM_TID_NUMBER)
|
if (heim_get_tid(path_element) == HEIM_TID_NUMBER)
|
||||||
idx = heim_number_get_int(path_element);
|
idx = heim_number_get_int(path_element);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
@@ -936,10 +936,16 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
|
|||||||
"and positive");
|
"and positive");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
if (idx < heim_array_get_length(node))
|
if (idx < heim_array_get_length(node)) {
|
||||||
next_node = heim_array_get_value(node, idx);
|
next_node = heim_array_get_value(node, idx);
|
||||||
else
|
} else if (idx == heim_array_get_length(node)) {
|
||||||
next_node = NULL;
|
next_node = NULL;
|
||||||
|
} else {
|
||||||
|
if (error)
|
||||||
|
*error = heim_error_create(EINVAL,
|
||||||
|
"Index for array in path is too large");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
} else if (node_type == HEIM_TID_DB && next_path_element != NULL) {
|
} else if (node_type == HEIM_TID_DB && next_path_element != NULL) {
|
||||||
if (error)
|
if (error)
|
||||||
*error = heim_error_create(EINVAL, "Interior node is a DB");
|
*error = heim_error_create(EINVAL, "Interior node is a DB");
|
||||||
@@ -951,26 +957,33 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
|
|||||||
|
|
||||||
/* Create missing interior node */
|
/* Create missing interior node */
|
||||||
if (next_node == NULL) {
|
if (next_node == NULL) {
|
||||||
next_node = heim_dict_create(size); /* no arrays or DBs, just dicts */
|
heim_dict_t new_node;
|
||||||
if (next_node == NULL) {
|
|
||||||
|
new_node = heim_dict_create(size); /* no arrays or DBs, just dicts */
|
||||||
|
if (new_node == NULL) {
|
||||||
ret = ENOMEM;
|
ret = ENOMEM;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node_type == HEIM_TID_DICT) {
|
if (node_type == HEIM_TID_DICT) {
|
||||||
ret = heim_dict_set_value(node, path_element, next_node);
|
ret = heim_dict_set_value(node, path_element, new_node);
|
||||||
|
heim_release(new_node);
|
||||||
|
|
||||||
|
next_node = heim_dict_get_value(node, path_element);
|
||||||
} else if (node_type == HEIM_TID_ARRAY &&
|
} else if (node_type == HEIM_TID_ARRAY &&
|
||||||
heim_number_get_int(path_element) <= heim_array_get_length(node)) {
|
heim_number_get_int(path_element) <= heim_array_get_length(node)) {
|
||||||
ret = heim_array_insert_value(node,
|
ret = heim_array_insert_value(node,
|
||||||
heim_number_get_int(path_element),
|
heim_number_get_int(path_element),
|
||||||
next_node);
|
new_node);
|
||||||
|
heim_release(new_node);
|
||||||
|
|
||||||
|
next_node = heim_array_get_value(node, idx);
|
||||||
} else {
|
} else {
|
||||||
ret = EINVAL;
|
ret = EINVAL;
|
||||||
if (error)
|
if (error)
|
||||||
*error = heim_error_create(ret, "Node in path not a "
|
*error = heim_error_create(ret, "Node in path not a "
|
||||||
"container");
|
"container");
|
||||||
}
|
}
|
||||||
heim_release(next_node);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user