]> granicus.if.org Git - php/commitdiff
fix faulty fix for Bug #40189, and provide real fix for the bug
authorGreg Beaver <cellog@php.net>
Sat, 12 Jan 2008 21:25:43 +0000 (21:25 +0000)
committerGreg Beaver <cellog@php.net>
Sat, 12 Jan 2008 21:25:43 +0000 (21:25 +0000)
ext/bz2/bz2_filter.c
ext/zlib/tests/bug.tar [new file with mode: 0644]
ext/zlib/tests/bug_40189.phpt [new file with mode: 0644]
ext/zlib/tests/bug_40189_2.phpt [new file with mode: 0644]
ext/zlib/zlib_filter.c

index 079c69c762821ba33a2f14777cc3e2a7f922fa04..8bf9c34df023a865aadf1183e56ddcae4062cb81 100644 (file)
@@ -108,12 +108,7 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
                        consumed += desired;
                        bin += desired;
 
-                       if (!desired) {
-                               flags |= PSFS_FLAG_FLUSH_CLOSE;
-                               break;
-                       }
-
-                       if (data->strm.avail_out < data->outbuf_len) {
+                       if (status == BZ_STREAM_END || data->strm.avail_out < data->outbuf_len) {
                                php_stream_bucket *out_bucket;
                                size_t bucketlen = data->outbuf_len - data->strm.avail_out;
                                out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
@@ -121,6 +116,13 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
                                data->strm.avail_out = data->outbuf_len;
                                data->strm.next_out = data->outbuf;
                                exit_status = PSFS_PASS_ON;
+                               if (status == BZ_STREAM_END) {
+                                       /* no more data to decompress, and nothing was spat out */
+                                       if (data->strm.avail_out >= data->outbuf_len) {
+                                               php_stream_bucket_delref(bucket TSRMLS_CC);
+                                       }
+                                       return PSFS_PASS_ON;
+                               }
                        }
                }
                php_stream_bucket_delref(bucket TSRMLS_CC);
diff --git a/ext/zlib/tests/bug.tar b/ext/zlib/tests/bug.tar
new file mode 100644 (file)
index 0000000..77fd778
Binary files /dev/null and b/ext/zlib/tests/bug.tar differ
diff --git a/ext/zlib/tests/bug_40189.phpt b/ext/zlib/tests/bug_40189.phpt
new file mode 100644 (file)
index 0000000..5ae51bf
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #40189 (endless loop in zlib.inflate stream filter)
+--SKIPIF--
+<?php if (!extension_loaded("zlib")) print "skip"; ?>
+--FILE--
+<?php
+// this string is an excerpt of a phar archive that caused an infinite loop
+$a = "\x3\x0\x85\x46\x2f\x7c\xc2\xaa\x69\x2b\x6d\xe5\xdb\xfe\xe4\x21\x8f\x0\x97\x21\x1d\x2\x0\x0\x0\x47\x42\x4d\x42";
+var_dump(base64_encode($a));
+$gp = fopen('test.other', 'wb');
+$fp = fopen('data://text/plain;base64,AwCFRi98wqppK23l2/7kIY8AlyEdAgAAAEdCTUI=', 'r');
+stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_READ);
+var_dump(stream_copy_to_stream($fp, $gp, 5));
+fclose($fp);
+fclose($gp);
+var_dump(file_get_contents('test.other'));
+?>
+--EXPECT--
+string(40) "AwCFRi98wqppK23l2/7kIY8AlyEdAgAAAEdCTUI="
+int(0)
+string(0) ""
diff --git a/ext/zlib/tests/bug_40189_2.phpt b/ext/zlib/tests/bug_40189_2.phpt
new file mode 100644 (file)
index 0000000..d89ffea
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Bug #40189 (test for truncated deflate, also part of erroneous fix for #40189)
+--SKIPIF--
+<?php if (!extension_loaded("zlib")) print "skip"; ?>
+--FILE--
+<?php
+$a = fopen('ext/zlib/tests/bug.tar', 'rb');
+stream_filter_append($a, 'zlib.deflate', STREAM_FILTER_READ, array('window' => 15+16));
+$b = fread($a, 4716032);
+var_dump(strlen($b));
+// when broken, this outputs "int(686904)"
+?>
+--EXPECT--
+int(1676116)
\ No newline at end of file
index 0bb2f170a44f62aba421b6d8bed34be79938bfa6..ab24f3afe8975cc0998708c00879e7f9cc215f90 100644 (file)
@@ -106,12 +106,7 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
                        data->strm.avail_in = 0;
                        bin += desired;
 
-                       if (!desired) {
-                               flags |= PSFS_FLAG_FLUSH_CLOSE;
-                               break;
-                       }
-
-                       if (data->strm.avail_out < data->outbuf_len) {
+                       if (status == Z_STREAM_END || data->strm.avail_out < data->outbuf_len) {
                                php_stream_bucket *out_bucket;
                                size_t bucketlen = data->outbuf_len - data->strm.avail_out;
                                out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
@@ -119,6 +114,13 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
                                data->strm.avail_out = data->outbuf_len;
                                data->strm.next_out = data->outbuf;
                                exit_status = PSFS_PASS_ON;
+                               if (status == Z_STREAM_END) {
+                                       /* no more data to decompress, and nothing was spat out */
+                                       if (data->strm.avail_out >= data->outbuf_len) {
+                                               php_stream_bucket_delref(bucket TSRMLS_CC);
+                                       }
+                                       return PSFS_PASS_ON;
+                               }
                        }
                }
                consumed += bucket->buflen;