From 4264db12fe71c5df46d5e1293a0811a99afbf0b0 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 29 Jul 2026 12:03:18 -0400 Subject: [PATCH] ext/session: report a rejected session cookie header php_session_send_cookie() discarded the result of sapi_add_header_ex() and always returned SUCCESS. When the SAPI refuses a Set-Cookie header carrying CR or LF, the warning it emits can reach a userland error handler that calls session_destroy(), and php_session_reset_id() then appends the released PS(id). Return what sapi_add_header_ex() reports so the caller stops before touching session state again. Closes GH-22923 --- ext/session/session.c | 4 +-- .../session_start_cookie_header_rejected.phpt | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 ext/session/tests/session_start_cookie_header_rejected.phpt diff --git a/ext/session/session.c b/ext/session/session.c index ba71d709a536..3ca5523246f5 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1497,10 +1497,10 @@ static zend_result php_session_send_cookie(void) /* {{{ */ php_session_remove_cookie(); /* remove already sent session ID cookie */ /* 'replace' must be 0 here, else a previous Set-Cookie header, probably sent with setcookie() will be replaced! */ - sapi_add_header_ex(estrndup(ZSTR_VAL(ncookie.s), ZSTR_LEN(ncookie.s)), ZSTR_LEN(ncookie.s), 0, 0); + zend_result result = sapi_add_header_ex(estrndup(ZSTR_VAL(ncookie.s), ZSTR_LEN(ncookie.s)), ZSTR_LEN(ncookie.s), 0, 0); smart_str_free(&ncookie); - return SUCCESS; + return result; } /* }}} */ diff --git a/ext/session/tests/session_start_cookie_header_rejected.phpt b/ext/session/tests/session_start_cookie_header_rejected.phpt new file mode 100644 index 000000000000..7a6c8cc1d3e6 --- /dev/null +++ b/ext/session/tests/session_start_cookie_header_rejected.phpt @@ -0,0 +1,31 @@ +--TEST-- +session_start() when the SAPI rejects the session cookie header +--INI-- +session.save_handler=files +session.name=PHPSESSID +session.gc_probability=0 +--EXTENSIONS-- +session +--FILE-- + "/\r\nX-Injected: yes"]); + +var_dump(session_start()); +var_dump(session_status() === PHP_SESSION_NONE); + +?> +--EXPECT-- +handler: Header may not contain more than a single header, new line detected +bool(false) +bool(true)