Skip to content

Fix infinite loop in sapi_header_op() for headers of 4 GiB or more - #24540

Closed
Marti2203 wants to merge 3 commits into
php:PHP-8.4from
Marti2203:fix-sapi-header-op-4gib
Closed

Marti2203 wants to merge 3 commits into
php:PHP-8.4from
Marti2203:fix-sapi-header-op-4gib

Conversation

@Marti2203

@Marti2203 Marti2203 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

The new line/NUL check in sapi_header_op() walks the header line with a uint32_t index, but header_line_len is a size_t:

uint32_t i;
for (i = 0; i < header_line_len; i++) {

For a header line of 4 GiB or more the index wraps around before it reaches the length, so the loop never ends and the request hangs, burning CPU until something kills it.

Any header of that size reaches the loop, for example header('X-Foo: ' . str_repeat('a', 2**32) . "\nX-Bar: b"), and so does session_start() with a cookie path, cookie domain or session id of 4 GiB or more (php_session_send_cookie() passes the full size_t length to sapi_add_header_ex()). It can only be triggered by the script itself and needs a very large memory_limit, so this is a robustness fix, not a security one.

Reproducer

<?php
ini_set('session.save_path', sys_get_temp_dir());
ini_set('session.use_cookies', '1');
ini_set('session.cookie_path', '/' . str_repeat('p', (1 << 32) + 16));
session_start();
echo "done\n";

Run with php -n -d memory_limit=-1 (needs about 17 GB of RAM).

  • Before: with a cookie path 64 bytes shorter than 4 GiB, session_start() returns after about 9 s. With the 4 GiB + 16 byte path it is still spinning in sapi_header_op() when timeout 90 kills it.
  • After: session_start() returns after about 9 s in both cases.

Fix

Use size_t for the index.

Test

ext/standard/tests/general_functions/header_over_4gib.phpt calls header() with a header line of 4 GiB followed by a new line and checks that the usual "new line detected" warning is raised. It needs more than 8 GB of RAM, so it follows the existing large-memory tests (e.g. ext/bz2/tests/gh20620.phpt): it only runs with RUN_RESOURCE_HEAVY_TESTS set, on 64-bit platforms, and not with SKIP_SLOW_TESTS.

  • Without the fix: the test times out.
  • With the fix: the test passes; without RUN_RESOURCE_HEAVY_TESTS it is skipped.
  • ext/session/tests, tests/basic and sapi/cli/tests pass (374 passed, 127 skipped, 1 expected fail, 0 failed).

This issue was found by an LLM-Enhanced Static Analysis Engine and verified manually.

🤖 Generated with Claude Code

The new line/NUL check iterated over the size_t header length with a
uint32_t index, which wraps around for header lines of 4 GiB or more,
so the loop never ended. session_start() reaches this with a cookie
path, domain or session id of that size. Use size_t for the index.
Comment thread ext/session/tests/session_cookie_path_over_4gib.phpt Outdated
Use header() directly, as suggested in review, so the test does not depend
on the session extension.

@LamentXU123 LamentXU123 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Can you add a NEWS entry?

@LamentXU123
LamentXU123 requested a review from jorgsowa October 22, 2026 15:23
@Marti2203

Copy link
Copy Markdown
Contributor Author

Thanks, added a NEWS entry under Core.

@LamentXU123

Copy link
Copy Markdown
Member

AFAIK this is a SAPI fix so should be under SAPI?

@jorgsowa jorgsowa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

LamentXU123 added a commit that referenced this pull request Oct 22, 2026
* PHP-8.6:
  Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (#24540)
@LamentXU123

Copy link
Copy Markdown
Member

Thanks!

brainexe pushed a commit to brainexe/php-src that referenced this pull request Oct 22, 2026
* PHP-8.4:
  Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (php#24540)
brainexe pushed a commit to brainexe/php-src that referenced this pull request Oct 22, 2026
* PHP-8.5:
  Fix infinite loop in sapi_header_op() for headers of 4 GiB or more (php#24540)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants