From 8b48fa72d359de89215f50cbf6ac8c77ae5de9b4 Mon Sep 17 00:00:00 2001 From: Comtea04 Date: Sun, 27 Sep 2026 15:06:22 +0900 Subject: 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 --- src/bplist.c | 9 +++++++-- src/plist.c | 16 +++++++++++++--- src/ptrarray.c | 15 ++++++++++----- src/ptrarray.h | 4 ++-- 4 files changed, 32 insertions(+), 12 deletions(-) (limited to 'src') 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); -- cgit v1.1-32-gdbae