Commit ee739e842b5 for php
commit ee739e842b5b250a03cd3e48f24e4e315dd331c2
Author: Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
Date: Mon Sep 28 15:36:16 2026 +0200
ext/standard: enforce max_filter_count (#23344)
Using more than 16 filters in a php://filter URL was deprecated in 8.6, and will fail in PHP 8.7.
RFC: https://wiki.php.net/rfc/limit-maximum-number-of-filter-chains
diff --git a/NEWS b/NEWS
index a6e87d987ca..da657a2611a 100644
--- a/NEWS
+++ b/NEWS
@@ -21,5 +21,7 @@ PHP NEWS
- Standard:
. Improved performance of array_splice() when inserting without removing
elements. (mehmetcansahin)
+ . Enforce max_filter_count: limit the number of filters that can be chained
+ in a php://filter URL. (Sjoerd Langkemper)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/UPGRADING b/UPGRADING
index 8c9bc4dac3f..5d551005042 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -19,6 +19,11 @@ PHP 8.7 UPGRADE NOTES
1. Backward Incompatible Changes
========================================
+- Standard:
+ . The number of filters that can be chained in a php://filter URL is limited
+ to 16 by default. Set the stream context option max_filter_count to change
+ this.
+
========================================
2. New Features
========================================
diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c
index cca9445801f..5d24c30727f 100644
--- a/ext/standard/php_fopen_wrapper.c
+++ b/ext/standard/php_fopen_wrapper.c
@@ -152,12 +152,10 @@ static zend_result php_stream_apply_filter_list(php_stream *stream, char *filter
php_stream_filter *temp_filter;
zend_long max_filter_count = max_filter_count_default;
- bool max_filter_count_configured = false;
if (context != NULL) {
zval *option_val = php_stream_context_get_option(context, "filter", "max_filter_count");
if (option_val) {
max_filter_count = zval_get_long(option_val);
- max_filter_count_configured = true;
}
}
@@ -167,13 +165,7 @@ static zend_result php_stream_apply_filter_list(php_stream *stream, char *filter
zend_long write_count = write_chain ? stream->writefilters.num_filters : 0;
if (read_count == max_filter_count || write_count == max_filter_count) {
- if (max_filter_count_configured) {
- return FAILURE;
- } else {
- // No max_filter_count configured; raise deprecation error if over default
- zend_error(E_DEPRECATED, "Using more than " ZEND_LONG_FMT " filters in a php://filter URL is deprecated, "
- "set this limit using the stream context option max_filter_count, or use stream_filter_append", max_filter_count_default);
- }
+ return FAILURE;
}
php_url_decode(p, strlen(p));
diff --git a/ext/standard/tests/filters/max_filter_chain.phpt b/ext/standard/tests/filters/max_filter_chain.phpt
index b93407eee97..40a0efb6b51 100644
--- a/ext/standard/tests/filters/max_filter_chain.phpt
+++ b/ext/standard/tests/filters/max_filter_chain.phpt
@@ -90,24 +90,30 @@ function createFilterChains($n, $resource) {
int(1)
# file_get_contents on 17 filters
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(9) "SEVENTEEN"
+Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
+bool(false)
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(9) "SEVENTEEN"
+Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
+bool(false)
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(9) "SEVENTEEN"
+Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
+bool(false)
# include on 17 filters
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-int(1)
+Warning: include(): Failed to open stream: too many filters in %s on line %d
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-int(1)
+Warning: include(): Failed opening %s
+bool(false)
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-int(1)
+Warning: include(): Failed to open stream: too many filters in %s on line %d
+
+Warning: include(): Failed opening %s
+bool(false)
+
+Warning: include(): Failed to open stream: too many filters in %s on line %d
+
+Warning: include(): Failed opening %s
+bool(false)
# file_get_contents on 3 filters, max_filter_count=2
Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
@@ -124,18 +130,18 @@ function createFilterChains($n, $resource) {
string(8) "NINETEEN"
# warning is only given once, even when we add two filters over the limit
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(8) "EIGHTEEN"
+Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
+bool(false)
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(8) "EIGHTEEN"
+Warning: file_get_contents(): Failed to open stream: too many filters in %s on line %d
+bool(false)
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-string(8) "EIGHTEEN"
+Warning: file_get_contents(): Failed to open stream: operation failed in %s on line %d
+bool(false)
# warn on too many write filters, even when number of read filters is OK
-Deprecated: Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append in %smax_filter_chain.php on line %d
-bool(true)
+Warning: fopen(): Failed to open stream: too many filters in %s on line %d
+bool(false)
# setting max_filter_count to -1 disables warning
string(6) "TWENTY"
string(6) "TWENTY"