diff --git a/NEWS b/NEWS index 3517d0eeb08..b3a9c4963ff 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) +- Streams: + . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). + (Jakub Zelenka) + 11 Apr 2024, PHP 8.2.18 - Core: diff --git a/ext/standard/tests/filters/gh13264.phpt b/ext/standard/tests/filters/gh13264.phpt new file mode 100644 index 00000000000..6456a082a1e --- /dev/null +++ b/ext/standard/tests/filters/gh13264.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-81475: Memory leak during stream filter failure +--SKIPIF-- + +--FILE-- + 15]); + +// Read the filtered stream line by line. +while (($line = fgets($stream)) !== false) { + $error = error_get_last(); + if ($error !== null) { + // An error is thrown but fgets didn't return false + var_dump(error_get_last()); + var_dump($line); + } +} + +fclose($stream); +?> +--EXPECTF-- + +Notice: fgets(): zlib: data error in %s on line %d +array(4) { + ["type"]=> + int(8) + ["message"]=> + string(25) "fgets(): zlib: data error" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) +} +string(7) "Hello 6" + diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index dcbfc381d29..8995471af45 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -196,22 +196,7 @@ php_stream_filter_status_t userfilter_filter( } if (buckets_in->head) { - php_stream_bucket *bucket; - php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade"); - while ((bucket = buckets_in->head)) { - /* Remove unconsumed buckets from the brigade */ - php_stream_bucket_unlink(bucket); - php_stream_bucket_delref(bucket); - } - } - if (ret != PSFS_PASS_ON) { - php_stream_bucket *bucket = buckets_out->head; - while (bucket != NULL) { - php_stream_bucket_unlink(bucket); - php_stream_bucket_delref(bucket); - bucket = buckets_out->head; - } } /* filter resources are cleaned up by the stream destructor, diff --git a/main/streams/streams.c b/main/streams/streams.c index d45a9bfab85..33f8b7e7a80 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -632,6 +632,17 @@ PHPAPI zend_result _php_stream_fill_read_buffer(php_stream *stream, size_t size) /* some fatal error. Theoretically, the stream is borked, so all * further reads should fail. */ stream->eof = 1; + /* free all data left in brigades */ + while ((bucket = brig_inp->head)) { + /* Remove unconsumed buckets from the input brigade */ + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } + while ((bucket = brig_outp->head)) { + /* Remove unconsumed buckets from the output brigade */ + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } efree(chunk_buf); return FAILURE; }