Commit 0870487b625 for php.net

commit 0870487b6256cbfbc12134cd52c599a92c1ac160
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Wed Jul 29 12:03:18 2026 -0400

    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

diff --git a/ext/session/session.c b/ext/session/session.c
index f03813c791d..2073ea55fe1 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1499,10 +1499,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 00000000000..6c3e3b78a3b
--- /dev/null
+++ b/ext/session/tests/session_start_cookie_header_rejected.phpt
@@ -0,0 +1,28 @@
+--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--
+<?php
+
+ob_start();
+
+set_error_handler(function (int $errno, string $errstr): bool {
+    echo "handler: ", $errstr, PHP_EOL;
+    return true;
+});
+
+session_set_cookie_params(['path' => "/\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)