]> granicus.if.org Git - php/commitdiff
Fixed bug #79468
authordinosaur <thedinosaurmail@gmail.com>
Mon, 13 Apr 2020 23:46:34 +0000 (07:46 +0800)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 14 Apr 2020 09:59:51 +0000 (11:59 +0200)
Close the stream filter resources when removing them from the stream.

NEWS
ext/standard/tests/filters/bug79468.phpt [new file with mode: 0644]
main/streams/streams.c

diff --git a/NEWS b/NEWS
index 9ebfbf1627324f0fa33903b2a5ba8c81badd1fd8..95e520e32ac8a6af715aa11dd450a41f2460c2a8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,10 @@ PHP                                                                        NEWS
   . Fixed bug #79441 (Segfault in mb_chr() if internal encoding is unsupported).
     (Girgias)
 
+- Standard:
+  . Fixed bug #79468 (SIGSEGV when closing stream handle with a stream filter
+    appended). (dinosaur)
+
 16 Apr 2020, PHP 7.3.17
 
 - Core:
diff --git a/ext/standard/tests/filters/bug79468.phpt b/ext/standard/tests/filters/bug79468.phpt
new file mode 100644 (file)
index 0000000..60a848e
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #79468     SIGSEGV when closing stream handle with a stream filter appended
+--SKIPIF--
+<?php
+$filters = stream_get_filters();
+if(! in_array( "string.rot13", $filters )) die( "skip rot13 filter not available." );
+?>
+--FILE--
+<?php
+$fp = fopen('php://temp', 'rb');
+$rot13_filter = stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE);
+fwrite($fp, "This is ");
+fclose($fp);
+try {
+    stream_filter_remove($rot13_filter);
+} catch (\Throwable $e) {
+    var_dump($e->getMessage());
+}
+?>
+--EXPECTF--
+Warning: stream_filter_remove(): Invalid resource given, not a stream filter in %s on line %d
index 5daf4fe83decf505fcabd50de5375003d8fc05d7..fb9c68007398ebab31337d45d9f8566d16449900 100644 (file)
@@ -476,9 +476,15 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
 
        if (close_options & PHP_STREAM_FREE_RELEASE_STREAM) {
                while (stream->readfilters.head) {
+                       if (stream->readfilters.head->res != NULL) {
+                               zend_list_close(stream->readfilters.head->res);
+                       }
                        php_stream_filter_remove(stream->readfilters.head, 1);
                }
                while (stream->writefilters.head) {
+                       if (stream->writefilters.head->res != NULL) {
+                               zend_list_close(stream->writefilters.head->res);
+                       }
                        php_stream_filter_remove(stream->writefilters.head, 1);
                }