From 4a9f0c8ac3360bb7b8be4e5a995264afcdfcee68 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 6 Sep 2026 10:54:51 -0400 Subject: [PATCH] session: close save handler before re-initializing an active session php_session_initialize() set the status to active and called the save handler's open() and read() without first closing a session that was already active, so session_reset() left the earlier open() unmatched. Abort the active session first, pairing every open() with a close(). Closes GH-23597 --- NEWS | 4 ++ ext/session/session.c | 4 ++ .../tests/session_reset_handler_close.phpt | 60 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 ext/session/tests/session_reset_handler_close.phpt diff --git a/NEWS b/NEWS index 1cc265f02e8d..4c8ab5f8e188 100644 --- a/NEWS +++ b/NEWS @@ -92,6 +92,10 @@ PHP NEWS . Fixed bug GH-23477 (Memory leak on duplicate native Phar manifest entries). (Weilin Du) +- Session: + . Fixed calling SessionHandler::open() twice without an intervening + close() when re-initializing an active session. (Ilia Alshanetsky) + - SOAP: . Fixed bug GH-23447 (Segfault when a class passed to SoapServer::setClass() fails to initialize). (Lazizbek Ergashev) diff --git a/ext/session/session.c b/ext/session/session.c index 2073ea55fe1f..abfce3b4b68c 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -420,6 +420,10 @@ static zend_result php_session_initialize(void) /* {{{ */ { zend_string *val = NULL; + if (PS(session_status) == php_session_active) { + php_session_abort(); + } + PS(session_status) = php_session_active; if (!PS(mod)) { diff --git a/ext/session/tests/session_reset_handler_close.phpt b/ext/session/tests/session_reset_handler_close.phpt new file mode 100644 index 000000000000..54bfc6b7f1d1 --- /dev/null +++ b/ext/session/tests/session_reset_handler_close.phpt @@ -0,0 +1,60 @@ +--TEST-- +Session reset closes the save handler before reopening it +--INI-- +session.use_cookies=0 +session.gc_probability=0 +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +Array +( + [0] => open + [1] => read + [2] => close + [3] => open + [4] => read +)