summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Comtea042026-09-27 15:06:22 +0900
committerGravatar Comtea042026-09-27 15:06:22 +0900
commit8b48fa72d359de89215f50cbf6ac8c77ae5de9b4 (patch)
tree07c02aa1437e53e0994ef0ec89edf752c4b309a8
parent32428abacb909988e8e960a8845a6430b17b6a60 (diff)
downloadlibplist-8b48fa72d359de89215f50cbf6ac8c77ae5de9b4.tar.gz
libplist-8b48fa72d359de89215f50cbf6ac8c77ae5de9b4.tar.bz2
ptrarray: Handle realloc() failure in ptr_array_insert()
ptr_array_insert() assigned the result of realloc() directly to pa->pdata and bumped the capacity without checking for failure, so on out-of-memory the old buffer was leaked and the following store or memmove() wrote through a NULL pointer. Keep the old buffer on failure and return -1 from ptr_array_insert() and ptr_array_add(). The callers now handle the error: - the array lookup cache (plist.c) is dropped instead of silently going out of sync with the node list; lookups then fall back to walking the children, as they do before the cache exists - bplist parsing (used_indexes) and serialization (objects) return PLIST_ERR_NO_MEM; ignoring the error in parse_bin_node_at_index() would otherwise loop forever since the array never grows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--src/bplist.c9
-rw-r--r--src/plist.c16
-rw-r--r--src/ptrarray.c15
-rw-r--r--src/ptrarray.h4
4 files changed, 32 insertions, 12 deletions
diff --git a/src/bplist.c b/src/bplist.c
index 7b08532..ea829c7 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -876,7 +876,10 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node
/* store node_index for current recursion level */
if ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
while ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
- ptr_array_add(bplist->used_indexes, (void*)(uintptr_t)node_index);
+ if (ptr_array_add(bplist->used_indexes, (void*)(uintptr_t)node_index) < 0) {
+ bplist->err = PLIST_ERR_NO_MEM;
+ return NULL;
+ }
}
} else {
ptr_array_set(bplist->used_indexes, (void*)(uintptr_t)node_index, bplist->level);
@@ -1106,7 +1109,9 @@ static plist_err_t serialize_plist(node_t node, void* data, uint32_t depth)
hash_table_insert(ser->ref_table, node, index_val);
// now append current node to object array
- ptr_array_add(ser->objects, node);
+ if (ptr_array_add(ser->objects, node) < 0) {
+ return PLIST_ERR_NO_MEM;
+ }
// now recurse on children
node_t ch;
diff --git a/src/plist.c b/src/plist.c
index 05af457..5ea6c12 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -898,7 +898,10 @@ static plist_t plist_copy_node(node_t root)
switch (f->type) {
case PLIST_ARRAY:
if (f->copydata->hashtable) {
- ptr_array_add((ptrarray_t*)f->copydata->hashtable, newch);
+ if (ptr_array_add((ptrarray_t*)f->copydata->hashtable, newch) < 0) {
+ ptr_array_free((ptrarray_t*)f->copydata->hashtable);
+ f->copydata->hashtable = NULL;
+ }
}
break;
@@ -987,7 +990,11 @@ static void _plist_array_post_insert(plist_t node, plist_t item, long n)
ptrarray_t *pa = (ptrarray_t*)((plist_data_t)((node_t)node)->data)->hashtable;
if (pa) {
/* store pointer to item in array */
- ptr_array_insert(pa, item, n);
+ if (ptr_array_insert(pa, item, n) < 0) {
+ /* lookup array would be out of sync, drop it */
+ ptr_array_free(pa);
+ ((plist_data_t)((node_t)node)->data)->hashtable = NULL;
+ }
return;
}
@@ -999,7 +1006,10 @@ static void _plist_array_post_insert(plist_t node, plist_t item, long n)
pa && current;
current = (plist_t)node_next_sibling((node_t)current))
{
- ptr_array_add(pa, current);
+ if (ptr_array_add(pa, current) < 0) {
+ ptr_array_free(pa);
+ pa = NULL;
+ }
}
((plist_data_t)((node_t)node)->data)->hashtable = pa;
}
diff --git a/src/ptrarray.c b/src/ptrarray.c
index 3a11031..bdcd428 100644
--- a/src/ptrarray.c
+++ b/src/ptrarray.c
@@ -40,12 +40,16 @@ void ptr_array_free(ptrarray_t *pa)
free(pa);
}
-void ptr_array_insert(ptrarray_t *pa, void *data, long array_index)
+int ptr_array_insert(ptrarray_t *pa, void *data, long array_index)
{
- if (!pa || !pa->pdata) return;
+ if (!pa || !pa->pdata) return -1;
long remaining = pa->capacity-pa->len;
if (remaining == 0) {
- pa->pdata = (void**)realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
+ void **newdata = (void**)realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
+ if (!newdata) {
+ return -1;
+ }
+ pa->pdata = newdata;
pa->capacity += pa->capacity_step;
}
if (array_index < 0 || array_index >= pa->len) {
@@ -55,11 +59,12 @@ void ptr_array_insert(ptrarray_t *pa, void *data, long array_index)
pa->pdata[array_index] = data;
}
pa->len++;
+ return 0;
}
-void ptr_array_add(ptrarray_t *pa, void *data)
+int ptr_array_add(ptrarray_t *pa, void *data)
{
- ptr_array_insert(pa, data, -1);
+ return ptr_array_insert(pa, data, -1);
}
void ptr_array_remove(ptrarray_t *pa, long array_index)
diff --git a/src/ptrarray.h b/src/ptrarray.h
index ed67351..28a521f 100644
--- a/src/ptrarray.h
+++ b/src/ptrarray.h
@@ -31,8 +31,8 @@ typedef struct ptrarray_t {
ptrarray_t *ptr_array_new(int capacity);
void ptr_array_free(ptrarray_t *pa);
-void ptr_array_add(ptrarray_t *pa, void *data);
-void ptr_array_insert(ptrarray_t *pa, void *data, long index);
+int ptr_array_add(ptrarray_t *pa, void *data);
+int ptr_array_insert(ptrarray_t *pa, void *data, long index);
void ptr_array_remove(ptrarray_t *pa, long index);
void ptr_array_set(ptrarray_t *pa, void *data, long index);
void* ptr_array_index(ptrarray_t *pa, long index);