[php-src] master: Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (#24540)

From: Date: Thu, 22 Oct 2026 16:59:38 +0000
Subject: [php-src] master: Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (#24540)
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-142591@lists.php.net to get a copy of this message
Author: Martin Mirchev (Marti2203) Committer: Weilin Du (LamentXU123) Date: 2026-10-23T00:48:30+08:00 Commit: https://github.com/php/php-src/commit/7ff3af0f428b3848c9cca6a13cdd6c6633d015dc Raw diff: https://github.com/php/php-src/commit/7ff3af0f428b3848c9cca6a13cdd6c6633d015dc.diff Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (#24540) The new line/NUL check uses a uint32_t index to scan a header whose length is size_t. For header lines of 4 GiB or more, the index wraps around and the request never finishes. This also affects session_start() when a cookie path, domain or session ID produces a header of that size. Use size_t for the index so it can reach the full header length. Add a resource-heavy regression test using header() directly, with a newline after 4 GiB to verify that header validation completes and emits the usual warning. The test requires a 64-bit platform and runs only when RUN_RESOURCE_HEAVY_TESTS is enabled and SKIP_SLOW_TESTS is unset. Closes #24540 Changed paths: A ext/standard/tests/general_functions/header_over_4gib.phpt M NEWS M main/SAPI.c Diff: diff --git a/NEWS b/NEWS index b2a90382e70f..883c9d7dee3e 100644 --- a/NEWS +++ b/NEWS @@ -104,6 +104,10 @@ PHP NEWS . Fixed a crash in readline_info() when completion_append_character contains a non-ASCII byte. (Weilin Du) +- SAPI: + . Fixed infinite loop in sapi_header_op() for headers of 4 GiB or more. + (Martin Mirchev) + - SOAP: . Fixed use of uninitialized func in do_request() on OOM bailout. (David Carlier) diff --git a/ext/standard/tests/general_functions/header_over_4gib.phpt b/ext/standard/tests/general_functions/header_over_4gib.phpt new file mode 100644 index 000000000000..a2075dfb27cd --- /dev/null +++ b/ext/standard/tests/general_functions/header_over_4gib.phpt @@ -0,0 +1,20 @@ +--TEST-- +header() with a header line longer than 4 GiB +--SKIPIF-- +<?php +if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test'); +if (PHP_INT_SIZE != 8) die('skip this test is for 64bit platforms only'); +if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request'); +?> +--INI-- +memory_limit=-1 +--FILE-- +<?php +// The new line/NUL check in sapi_header_op() used a 32-bit index, so a header +// line of 4 GiB or more made it loop forever. +header('X-Foo: ' . str_repeat('a', 2**32) . "\nX-Bar: b"); +echo "Done\n"; +?> +--EXPECTF-- +Warning: Header may not contain more than a single header, new line detected in %s on line %d +Done diff --git a/main/SAPI.c b/main/SAPI.c index dbc6ed163309..4b6b7b0c90e6 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -742,7 +742,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) return SUCCESS; } else { /* new line/NUL character safety check */ - uint32_t i; + size_t i; for (i = 0; i < header_line_len; i++) { /* RFC 7230 ch. 3.2.4 deprecates folding support */ if (header_line[i] == '\n' || header_line[i] == '\r') {

« previous php.cvs (#142591) next »