From 85275eaae0333cd99a208bb4ff4d26315a31b792 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 31 Dec 2025 00:06:35 +0100 Subject: [PATCH 1/2] bz2: Fix truncation of total output size causing erroneous errors Also switch to uint64_t as that's used on master and makes the code simpler to fix. Co-authored-by: Arnaud Le Blanc --- ext/bz2/bz2.c | 17 ++++------------- ext/bz2/tests/gh20807.phpt | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 ext/bz2/tests/gh20807.phpt diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 583d7f475a555..e43915e1992fd 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -502,11 +502,7 @@ PHP_FUNCTION(bzdecompress) size_t source_len; int error; bool small = 0; -#ifdef PHP_WIN32 - unsigned __int64 size = 0; -#else - unsigned long long size = 0; -#endif + uint64_t size = 0; bz_stream bzs; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &source, &source_len, &small)) { @@ -531,27 +527,22 @@ PHP_FUNCTION(bzdecompress) while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; - size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; -#ifndef ZEND_ENABLE_ZVAL_LONG64 + size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32; if (size > SIZE_MAX) { /* no reason to continue if we're going to drop it anyway */ break; } -#endif dest = zend_string_safe_realloc(dest, 1, bzs.avail_out+1, (size_t) size, 0); bzs.next_out = ZSTR_VAL(dest) + size; } if (error == BZ_STREAM_END || error == BZ_OK) { - size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; -#ifndef ZEND_ENABLE_ZVAL_LONG64 + size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32; if (UNEXPECTED(size > SIZE_MAX)) { php_error_docref(NULL, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX); zend_string_efree(dest); RETVAL_LONG(BZ_MEM_ERROR); - } else -#endif - { + } else { dest = zend_string_safe_realloc(dest, 1, (size_t)size, 1, 0); ZSTR_LEN(dest) = (size_t)size; ZSTR_VAL(dest)[(size_t)size] = '\0'; diff --git a/ext/bz2/tests/gh20807.phpt b/ext/bz2/tests/gh20807.phpt new file mode 100644 index 0000000000000..2cfd66fe0cb9b --- /dev/null +++ b/ext/bz2/tests/gh20807.phpt @@ -0,0 +1,17 @@ +--TEST-- +Truncation of total output size causing erroneous size and data +--EXTENSIONS-- +bz2 +--INI-- +memory_limit=-1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(40) "d4b5e52ed34a774fa645f94369b0c61375436d30" From d2f6d82c1e81504a9f3171ecf4a17d43031c442e Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Fri, 27 Feb 2026 22:50:45 +0100 Subject: [PATCH 2/2] fixup --- ext/bz2/tests/gh20807.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/bz2/tests/gh20807.phpt b/ext/bz2/tests/gh20807.phpt index 2cfd66fe0cb9b..8d1e0cb40e4fd 100644 --- a/ext/bz2/tests/gh20807.phpt +++ b/ext/bz2/tests/gh20807.phpt @@ -8,6 +8,8 @@ memory_limit=-1 --FILE--