]> granicus.if.org Git - php/commitdiff
Fix bug #72837 - integer overflow in bzdecompress caused heap corruption
authorAnatol Belski <ab@php.net>
Tue, 16 Aug 2016 10:34:25 +0000 (12:34 +0200)
committerAnatol Belski <ab@php.net>
Tue, 16 Aug 2016 10:34:25 +0000 (12:34 +0200)
Conflicts:
ext/bz2/bz2.c

ext/bz2/bz2.c

index bc6379aeeaf8aae016c701b6a43d2828541b24a5..60bb71ee8d70307b02264e7044724b88efe7b524 100644 (file)
@@ -594,16 +594,26 @@ static PHP_FUNCTION(bzdecompress)
                /* 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;
+               if (size > SIZE_MAX) {
+                       /* no reason to continue if we're going to drop it anyway */
+                       break;
+               }
                dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size );
                bzs.next_out = dest + size;
        }
 
        if (error == BZ_STREAM_END || error == BZ_OK) {
                size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
-               dest = safe_erealloc(dest, 1, (size_t) size, 1);
-               dest[size] = '\0';
-               RETVAL_STRINGL(dest, (int) size);
-               efree(dest);
+               if (size > SIZE_MAX) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
+                       efree(dest);
+                       RETVAL_LONG(BZ_MEM_ERROR);
+               } else {
+                       dest = safe_erealloc(dest, 1, (size_t) size, 1);
+                       dest[size] = '\0';
+                       RETVAL_STRINGL(dest, (size_t) size);
+                       efree(dest);
+               }
        } else { /* real error */
                efree(dest);
                RETVAL_LONG(error);