From 88694797e9f4949bd4f59174d612792fed6c6ea9 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Thu, 2 Jul 2026 11:54:29 +0000 Subject: [PATCH] Check whether stream correctly ends in dechunk At the end of the stream, we expect to have read the trailer. Check whether the chunked encoding is at the end of the encoded data when the stream ends. This makes it more difficult to abuse the dechunk filter for abuse. Related to #21983 --- ext/standard/filters.c | 5 ++ ext/standard/tests/filters/chunked_002.phpt | 2 +- .../tests/filters/chunked_invalid.phpt | 53 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/filters/chunked_invalid.phpt diff --git a/ext/standard/filters.c b/ext/standard/filters.c index c0741b46074e..127d7c144416 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -1949,6 +1949,11 @@ static php_stream_filter_status_t php_chunked_filter( *bytes_consumed = consumed; } + if ((flags & PSFS_FLAG_FLUSH_CLOSE) && data->state != CHUNK_TRAILER) { + php_error_docref(NULL, E_WARNING, "Stream filter (dechunk): unexpected end of stream"); + return PSFS_ERR_FATAL; + } + return PSFS_PASS_ON; } diff --git a/ext/standard/tests/filters/chunked_002.phpt b/ext/standard/tests/filters/chunked_002.phpt index 7114e278e3bd..c68bd19e801b 100644 --- a/ext/standard/tests/filters/chunked_002.phpt +++ b/ext/standard/tests/filters/chunked_002.phpt @@ -39,7 +39,7 @@ fclose($buffer); $buffer = fopen('php://temp', 'w+'); stream_filter_append($buffer, 'dechunk', STREAM_FILTER_WRITE); -fwrite($buffer, "5\r\nHello\r\n"); +fwrite($buffer, "5\r\nHello\r\n0\r\n"); $data = stream_get_contents($buffer, -1, 0); var_dump($data); diff --git a/ext/standard/tests/filters/chunked_invalid.phpt b/ext/standard/tests/filters/chunked_invalid.phpt new file mode 100644 index 000000000000..f6a751b4dd24 --- /dev/null +++ b/ext/standard/tests/filters/chunked_invalid.phpt @@ -0,0 +1,53 @@ +--TEST-- +Chunked encoding with invalid values +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + +--EXPECTF-- + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) "" + +Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d +string(0) ""