Skip to content

Commit d33d61b

Browse files
committed
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.
1 parent dabcd74 commit d33d61b

File tree

1 file changed

+4
-13
lines changed

1 file changed

+4
-13
lines changed

ext/bz2/bz2.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -502,11 +502,7 @@ PHP_FUNCTION(bzdecompress)
502502
size_t source_len;
503503
int error;
504504
bool small = 0;
505-
#ifdef PHP_WIN32
506-
unsigned __int64 size = 0;
507-
#else
508-
unsigned long long size = 0;
509-
#endif
505+
uint64_t size = 0;
510506
bz_stream bzs;
511507

512508
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &source, &source_len, &small)) {
@@ -531,27 +527,22 @@ PHP_FUNCTION(bzdecompress)
531527
while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
532528
/* compression is better then 2:1, need to allocate more memory */
533529
bzs.avail_out = source_len;
534-
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
535-
#ifndef ZEND_ENABLE_ZVAL_LONG64
530+
size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32;
536531
if (size > SIZE_MAX) {
537532
/* no reason to continue if we're going to drop it anyway */
538533
break;
539534
}
540-
#endif
541535
dest = zend_string_safe_realloc(dest, 1, bzs.avail_out+1, (size_t) size, 0);
542536
bzs.next_out = ZSTR_VAL(dest) + size;
543537
}
544538

545539
if (error == BZ_STREAM_END || error == BZ_OK) {
546-
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
547-
#ifndef ZEND_ENABLE_ZVAL_LONG64
540+
size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32;
548541
if (UNEXPECTED(size > SIZE_MAX)) {
549542
php_error_docref(NULL, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
550543
zend_string_efree(dest);
551544
RETVAL_LONG(BZ_MEM_ERROR);
552-
} else
553-
#endif
554-
{
545+
} else {
555546
dest = zend_string_safe_realloc(dest, 1, (size_t)size, 1, 0);
556547
ZSTR_LEN(dest) = (size_t)size;
557548
ZSTR_VAL(dest)[(size_t)size] = '\0';

0 commit comments

Comments
 (0)