[php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6
| From: | Weilin Du | Date: | Fri, 09 Oct 2026 19:59:12 +0000 |
| Subject: | [php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6 | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142133@lists.php.net to get a copy of this message | ||
Author: Weilin Du (LamentXU123)
Date: 2026-10-10T03:47:08+08:00
Commit: https://github.com/php/php-src/commit/70e083cb05fdddad332df8c71fa19e1e3cd6e0fb
Raw diff: https://github.com/php/php-src/commit/70e083cb05fdddad332df8c71fa19e1e3cd6e0fb.diff
Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
Fix use-after-free when removing a failing zlib.inflate filter (#24176)
Changed paths:
A ext/zlib/tests/zlib_filter_inflate_error_handler_removes_filter.phpt
M NEWS
M ext/zlib/zlib_filter.c
Diff:
diff --git a/NEWS b/NEWS
index 7d7578074147..99cee71b9d1a 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,10 @@ PHP NEWS
is called from a progress or cancel callback during close().
(Ilia Alshanetsky)
+- Zlib:
+ . Fixed use-after-free when an error handler removes a failing zlib.inflate
+ filter (GH-24176). (Edmond)
+
08 Oct 2026, PHP 8.6.0RC3
- BCMath:
diff --git a/ext/zlib/tests/zlib_filter_inflate_error_handler_removes_filter.phpt
b/ext/zlib/tests/zlib_filter_inflate_error_handler_removes_filter.phpt
new file mode 100644
index 000000000000..ee5bab1052fc
--- /dev/null
+++ b/ext/zlib/tests/zlib_filter_inflate_error_handler_removes_filter.phpt
@@ -0,0 +1,30 @@
+--TEST--
+zlib.inflate filter removed by the error handler of its own notice
+--EXTENSIONS--
+zlib
+--FILE--
+<?php
+$fp = fopen('php://memory', 'w+');
+$filter = stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_WRITE);
+set_error_handler(function (int $errno, string $errstr) use (&$filter) {
+ echo $errstr, "\n";
+ var_dump(stream_filter_remove($filter));
+ return true;
+});
+var_dump(fwrite($fp, "\xff\xff\xff\xff"));
+
+$fp = fopen('php://memory', 'w+');
+fwrite($fp, "\xff\xff\xff\xff");
+rewind($fp);
+$filter = stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_READ);
+var_dump(fread($fp, 10));
+echo "Done\n";
+?>
+--EXPECT--
+fwrite(): zlib: data error
+bool(true)
+bool(false)
+fread(): zlib: data error
+bool(true)
+bool(false)
+Done
diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c
index a597a9b391cc..3cdfab91be2d 100644
--- a/ext/zlib/zlib_filter.c
+++ b/ext/zlib/zlib_filter.c
@@ -89,11 +89,12 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
exit_status = PSFS_PASS_ON;
} else if (status != Z_OK && status != Z_BUF_ERROR) {
/* Something bad happened */
- php_error_docref(NULL, E_NOTICE, "zlib: %s", zError(status));
php_stream_bucket_delref(bucket);
/* reset these because despite the error the filter may be used again */
data->strm.next_in = data->inbuf;
data->strm.avail_in = 0;
+ /* Last: an error handler may remove this filter and free data. */
+ php_error_docref(NULL, E_NOTICE, "zlib: %s", zError(status));
return PSFS_ERR_FATAL;
}
desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */