diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index a8153d7d119..91e694f58f4 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -537,18 +537,17 @@ 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; + size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32; if (UNEXPECTED(size > SIZE_MAX)) { /* no reason to continue if we're going to drop it anyway */ break; } - 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; + 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 %zu", SIZE_MAX); zend_string_efree(dest); diff --git a/ext/bz2/tests/gh20807.phpt b/ext/bz2/tests/gh20807.phpt new file mode 100644 index 00000000000..8d1e0cb40e4 --- /dev/null +++ b/ext/bz2/tests/gh20807.phpt @@ -0,0 +1,19 @@ +--TEST-- +Truncation of total output size causing erroneous size and data +--EXTENSIONS-- +bz2 +--INI-- +memory_limit=-1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(40) "d4b5e52ed34a774fa645f94369b0c61375436d30"