From 78d767436ae0e64cc2a89ddea045809798ac82c0 Mon Sep 17 00:00:00 2001 From: Filippo Tedeschi Date: Thu, 24 Sep 2026 20:36:25 +0200 Subject: [PATCH] zip_close: check for allocation overflow and set error on failure In zip_close(), survivors is a 64-bit integer (zip_uint64_t). On 32-bit platforms, the allocation size calculation sizeof(filelist[0]) * (size_t)survivors could overflow size_t when survivors exceeds SIZE_MAX / sizeof(filelist[0]), leading to an undersized buffer allocation and subsequent out-of-bounds writes. Additionally: - When survivors == 0 (e.g. keeping an empty archive), avoid calling malloc(0), which may return NULL on some platforms/allocators and cause spurious failure. - Ensure zip_error_set(&za->error, ZIP_ER_MEMORY, 0) is called if allocation fails so callers receive a consistent error code. - Guard the qsort() call to avoid passing a NULL pointer when survivors == 0. --- lib/zip_close.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/zip_close.c b/lib/zip_close.c index 50518f5cf..dee013185 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c @@ -89,7 +89,16 @@ ZIP_EXTERN int zip_close(zip_t *za) { return -1; } - if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL) { + if (survivors > SIZE_MAX / sizeof(filelist[0])) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (survivors == 0) { + filelist = NULL; + } + else if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } @@ -119,7 +128,7 @@ ZIP_EXTERN int zip_close(zip_t *za) { return -1; } - if (ZIP_WANT_TORRENTZIP(za)) { + if (ZIP_WANT_TORRENTZIP(za) && survivors > 0) { qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names); }