From e5c2b3a09ceee28486a47b279ca6bff84b104837 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 3 Feb 2025 12:50:34 +0100 Subject: [PATCH] Prevent unsigned overflow in php_handle_swc() The multiplication of `ZSTR_LEN(bufz)` with the `factor` can easily overflow on LLP64 architectures, causing a smaller `buf` to be allocated than expected. While there are no security implications, calling `uncompress()` with the small buffer cannot be successful (`Z_BUF_ERROR`). We avoid such superfluous calls by bailing out of the loop early in case of an overflow condition. Note that `safe_emalloc()` would not help here, since that will not prevent 32bit unsigned overflow on 64bit architectures. --- ext/standard/image.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext/standard/image.c b/ext/standard/image.c index 177e87d21b599..eeb1f1fa2813a 100644 --- a/ext/standard/image.c +++ b/ext/standard/image.c @@ -203,9 +203,14 @@ static struct gfxinfo *php_handle_swc(php_stream * stream) */ do { - szlength = ZSTR_LEN(bufz) * (factor <<= 1); + factor <<= 1; + if (ZSTR_LEN(bufz) > ULONG_MAX / factor) { + status = Z_MEM_ERROR; + break; + } + szlength = (unsigned long) (ZSTR_LEN(bufz) * factor); buf = erealloc(buf, szlength); - status = uncompress(buf, &szlength, (unsigned char *) ZSTR_VAL(bufz), ZSTR_LEN(bufz)); + status = uncompress(buf, &szlength, (unsigned char *) ZSTR_VAL(bufz), (unsigned long) ZSTR_LEN(bufz)); } while ((status==Z_BUF_ERROR)&&(factor