Repository navigation
Bug: Memory leak of the last response headers after a nested HTTP request - #24201
Merged
Merged
Conversation
php_stream_url_wrap_http() releases BG(last_http_headers) before the request and copies the new headers over it after. A request made while the first one runs, from its notification callback, stores its own headers there in between, and the copy overwrote that array without releasing it.
ndossche
approved these changes
Oct 10, 2026
ndossche
left a comment
Member
There was a problem hiding this comment.
Thanks.
This is a bit of a stupid edge case...
It also makes me wonder if the lines 1275-1276 should be moved to else branch of the check at line 1282; so we don't have to dtor the headers twice...
Contributor
Author
Like this? php_stream *php_stream_url_wrap_http(
php_stream_wrapper *wrapper,
const char *path,
const char *mode,
int options,
zend_string **opened_path,
php_stream_context *context STREAMS_DC)
{
php_stream *stream;
zval headers;
ZVAL_UNDEF(&headers);
stream = php_stream_url_wrap_http_ex(
wrapper, path, mode, options, opened_path, context,
PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT, &headers STREAMS_CC);
if (!Z_ISUNDEF(headers)) {
/* A request made from a notification callback may have stored its own headers meanwhile. */
zval_ptr_dtor(&BG(last_http_headers));
ZVAL_COPY(&BG(last_http_headers), &headers);
if (FAILURE == zend_set_local_var_str(
"http_response_header", sizeof("http_response_header")-1, &headers, 0)) {
zval_ptr_dtor(&headers);
}
} else {
zval_ptr_dtor(&BG(last_http_headers));
ZVAL_UNDEF(&BG(last_http_headers));
}
return stream;
} |
Member
|
Yes indeed |
The release before the request is dropped: a single release after it covers both the previous request's headers and those stored by a nested one.
Girgias
added a commit
that referenced
this pull request
Oct 14, 2026
* PHP-8.6:
Update NEWS
ext/standard/tests: work around Windows quoting with tempfiles.
.github/scripts/windows: pass an extension_dir to the test runner.
{ext/standard,sapi/cli}/tests: pass TEST_PHP_EXTRA_ARGS to php
ext/standard/tests: pass TEST_PHP_EXTRA_ARGS to some proc_open() tests
sapi/cli/tests/023.phpt: support TEST_PHP_EXTRA_ARGS
std: Fix memory leak of the last response headers after a nested HTTP request (#24201)
Fiber: hold the object a callable resolved to in the creating frame (#24134)
Girgias
added a commit
to Girgias/php-src
that referenced
this pull request
Oct 14, 2026
* PHP-8.4:
Update NEWS
ext/standard/tests: work around Windows quoting with tempfiles.
.github/scripts/windows: pass an extension_dir to the test runner.
{ext/standard,sapi/cli}/tests: pass TEST_PHP_EXTRA_ARGS to php
ext/standard/tests: pass TEST_PHP_EXTRA_ARGS to some proc_open() tests
sapi/cli/tests/023.phpt: support TEST_PHP_EXTRA_ARGS
std: Fix memory leak of the last response headers after a nested HTTP request (php#24201)
Fiber: hold the object a callable resolved to in the creating frame (php#24134)
Girgias
added a commit
to Girgias/php-src
that referenced
this pull request
Oct 14, 2026
* PHP-8.5:
Update NEWS
ext/standard/tests: work around Windows quoting with tempfiles.
.github/scripts/windows: pass an extension_dir to the test runner.
{ext/standard,sapi/cli}/tests: pass TEST_PHP_EXTRA_ARGS to php
ext/standard/tests: pass TEST_PHP_EXTRA_ARGS to some proc_open() tests
sapi/cli/tests/023.phpt: support TEST_PHP_EXTRA_ARGS
std: Fix memory leak of the last response headers after a nested HTTP request (php#24201)
Fiber: hold the object a callable resolved to in the creating frame (php#24134)
arnaud-lb
added a commit
to heathdutton/php-src
that referenced
this pull request
Oct 15, 2026
* up/PHP-8.4: (3595 commits) Fix Windows quoting in proc_open tests (php#24343) Pin macOS CI to OpenSSL 3 (php#24332) Zend: zend_call_stack_get_netbsd_pthread() pthread attribute leak. Revert "ext/standard/tests: work around Windows quoting with tempfiles." Update NEWS ext/standard/tests: work around Windows quoting with tempfiles. .github/scripts/windows: pass an extension_dir to the test runner. {ext/standard,sapi/cli}/tests: pass TEST_PHP_EXTRA_ARGS to php ext/standard/tests: pass TEST_PHP_EXTRA_ARGS to some proc_open() tests sapi/cli/tests/023.phpt: support TEST_PHP_EXTRA_ARGS std: Fix memory leak of the last response headers after a nested HTTP request (php#24201) Fiber: hold the object a callable resolved to in the creating frame (php#24134) Fix v142 ARM64 hash and floating point results (php#24317) Use the default archive names for Windows ARM64 builds (php#24313) ext/gd: Drop useless and doubtful MSVC specific code (libgd/libgd@f1480ab) (php#24316) ext/session: do not reuse session state a save handler tore down Fix phpGH-24293: Segfault with an empty password in MariaDB PAM (php#24294) Fix phpGH-24289: finfo::file() reports the wrong argument number Fix phpGH-24260: querySelectorAll() returns duplicate elements for selector lists Fix escape analysis for objects implementing ArrayAccess ...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
php_stream_url_wrap_http()releasesBG(last_http_headers)before the request and copies the new headers over it after the request. A request made from the notification callback of a running one stores its own headers there in between, and the outer copy overwrote that array without releasing it.Reproduction (debug build, no extensions beyond pcntl and posix for the test server):
Expected: no leak. Actual:
=== Total 4 memory leaks detected ===(the nested request's header array).The fix releases the stored array once, after the request, instead of before it. After the call
http_get_last_response_headers()returns the outer request's headers, as before. During the request, a notification callback now sees the previous request's headers instead ofnull.Test:
ext/standard/tests/http/http_response_header_nested_request.phpt(fails on PHP-8.4 debug without the fix with the leak report, passes with it). The leak report comes from debug builds; a release build reports the leak only under ASAN or valgrind.