diff options
| author | 2026-11-05 12:01:59 +0100 | |
|---|---|---|
| committer | 2026-11-05 12:01:59 +0100 | |
| commit | 4dc93bc274867b42aa82fc91ee4d5878d23a3f36 (patch) | |
| tree | 11c566b80561bb44018bceea028ea03d47e53458 /src/bytearray.c | |
| parent | f252f243f9774b2b830172b49aa340d6994d8081 (diff) | |
| download | libplist-4dc93bc274867b42aa82fc91ee4d5878d23a3f36.tar.gz libplist-4dc93bc274867b42aa82fc91ee4d5878d23a3f36.tar.bz2 | |
Harden allocation failure handling and size arithmetic
- check malloc/calloc/realloc results in constructors, the JSON and
OpenStep writers, the XML text-part helpers and base64 decoding, and
return PLIST_ERR_NO_MEM instead of asserting or dereferencing NULL
- guard size calculations against overflow in the UTF-8/UTF-16BE
conversions, ptrarray, and bytearray
- make hash_table_insert() report failure instead of silently dropping
the entry; writers propagate PLIST_ERR_NO_MEM, and dict lookup caches
are discarded so lookups fall back to a linear search
- don't overwrite an earlier parse error code in the XML parser, and
report PLIST_ERR_NO_MEM when reading text content fails for lack of memory
- OpenStep parser: check node/data/string allocations and dict/array
insertion results
Based on #323 by bg0d-droid.
Co-authored-by: bg0d-droid <81825610+bg0d-droid@users.noreply.github.com>
Diffstat (limited to 'src/bytearray.c')
| -rw-r--r-- | src/bytearray.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/bytearray.c b/src/bytearray.c index 89c5ec7..19303e0 100644 --- a/src/bytearray.c +++ b/src/bytearray.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <string.h> +#include <stdint.h> #include "bytearray.h" #define PAGE_SIZE 4096 @@ -26,8 +27,24 @@ bytearray_t *byte_array_new(size_t initial) { bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); - a->capacity = (initial > PAGE_SIZE) ? (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; + if (!a) { + return NULL; + } + if (initial > PAGE_SIZE) { + if (initial > SIZE_MAX - (PAGE_SIZE-1)) { + /* rounding up to the page size would overflow */ + free(a); + return NULL; + } + a->capacity = (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)); + } else { + a->capacity = PAGE_SIZE; + } a->data = malloc(a->capacity); + if (!a->data) { + free(a); + return NULL; + } a->len = 0; a->stream = NULL; return a; @@ -36,6 +53,9 @@ bytearray_t *byte_array_new(size_t initial) bytearray_t *byte_array_new_for_stream(FILE *stream) { bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); + if (!a) { + return NULL; + } a->capacity = (size_t)-1; a->data = NULL; a->len = 0; @@ -57,9 +77,15 @@ void byte_array_grow(bytearray_t *ba, size_t amount) if (ba->stream || !ba->data) { return; } - size_t increase = (amount > PAGE_SIZE) ? (amount+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; - if (increase < amount || ba->capacity + increase < ba->capacity) { - /* size overflow */ + size_t increase; + if (amount > PAGE_SIZE) { + /* round up to the page size, guarding against integer overflow */ + increase = (amount <= SIZE_MAX - (PAGE_SIZE-1)) ? ((amount+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1))) : 0; + } else { + increase = PAGE_SIZE; + } + if (increase == 0 || increase > SIZE_MAX - ba->capacity) { + /* integer overflow */ free(ba->data); ba->data = NULL; ba->len = 0; @@ -101,6 +127,10 @@ void byte_array_append(bytearray_t *ba, void *buf, size_t len) #endif } } else { + if (len > SIZE_MAX - ba->len) { + /* integer overflow when computing the new total length */ + return; + } size_t remaining = ba->capacity-ba->len; if (len > remaining) { size_t needed = len - remaining; |
