]> granicus.if.org Git - php/commitdiff
Fixed bug #79468
authordinosaur <thedinosaurmail@gmail.com>
Mon, 13 Apr 2020 23:46:34 +0000 (07:46 +0800)
committerSara Golemon <pollita@php.net>
Tue, 14 Apr 2020 14:27:28 +0000 (10:27 -0400)
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 7e551b1d094a2d18e327d4c83974c55e7bb583b2..a1530faa038a41529d3d778f46d5a84bda1d5624 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP                                                                        NEWS
 ?? ??? 2020, PHP 7.2.30
 
 - Standard:
+  . Fixed bug #79468 (SIGSEGV when closing stream handle with a stream filter
+    appended). (dinosaur)
   . Fixed bug #79330 (shell_exec() silently truncates after a null byte). (stas)
   . Fixed bug #79465 (OOB Read in urldecode()). (stas)
 
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 b504711db36dd71b2a56045a250a66dec3bf17c8..bf9537d33c053dac14b69120dfce1e1c2dd7cdde 100644 (file)
@@ -477,9 +477,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);
                }