From bc426f11e96aa1f4462e2b7df4c2b11b1aca01bd Mon Sep 17 00:00:00 2001 From: lazerg Date: Wed, 5 Aug 2026 15:58:06 +0500 Subject: [PATCH 1/2] Fix GH-23061: SessionHandler::create_sid() failure leaks memory in debug build --- NEWS | 2 ++ ext/session/session.c | 8 +++++++ .../tests/user_session_module/gh23061.phpt | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 ext/session/tests/user_session_module/gh23061.phpt diff --git a/NEWS b/NEWS index 474db936ef15..549bb342c3f7 100644 --- a/NEWS +++ b/NEWS @@ -41,6 +41,8 @@ PHP NEWS . Fix corruption in mod_mm. (ndossche) . Fixed bug GH-23043 (broken session id code can cause zend_mm_heap corrupted). (ndossche) + . Fixed bug GH-23061 (SessionHandler::create_sid() callback failure leaks + memory in debug build). (Lazizbek Ergashev) - Sockets: . Fixed various memory related issues in ext/sockets. (David Carlier) diff --git a/ext/session/session.c b/ext/session/session.c index 6380505ae951..a6b65ff57f18 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -145,6 +145,14 @@ static void php_rshutdown_session_globals(void) /* {{{ */ PS(mod)->s_close(&PS(mod_data)); } zend_end_try(); } + /* The user handler may not have closed the default handler it opened, e.g. because a pending + * exception prevented its close callback from running at all */ + if (PS(mod_user_is_open)) { + zend_try { + PS(default_mod)->s_close(&PS(mod_data)); + } zend_end_try(); + PS(mod_user_is_open) = false; + } if (PS(id)) { zend_string_release_ex(PS(id), 0); PS(id) = NULL; diff --git a/ext/session/tests/user_session_module/gh23061.phpt b/ext/session/tests/user_session_module/gh23061.phpt new file mode 100644 index 000000000000..f3756e3462d0 --- /dev/null +++ b/ext/session/tests/user_session_module/gh23061.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-23061 (SessionHandler::create_sid() callback failure leaks memory in debug build) +--EXTENSIONS-- +session +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Error: Session id must be a string From 4132ff3a2cfbec6fa39b25dc2d33a8f3b17af392 Mon Sep 17 00:00:00 2001 From: lazerg Date: Fri, 7 Aug 2026 16:04:10 +0500 Subject: [PATCH 2/2] Close the leaked default handler in php_session_abort() --- ext/session/session.c | 6 +++ .../user_session_module/gh23061-abort.phpt | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 ext/session/tests/user_session_module/gh23061-abort.phpt diff --git a/ext/session/session.c b/ext/session/session.c index a6b65ff57f18..495be3fb202f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1768,6 +1768,12 @@ static zend_result php_session_abort(void) /* {{{ */ if (PS(mod_data) || PS(mod_user_implemented)) { PS(mod)->s_close(&PS(mod_data)); } + /* The user handler may not have closed the default handler it opened, e.g. because a pending + * exception prevented its close callback from running at all */ + if (PS(mod_user_is_open)) { + PS(default_mod)->s_close(&PS(mod_data)); + PS(mod_user_is_open) = false; + } PS(session_status) = php_session_none; return SUCCESS; } diff --git a/ext/session/tests/user_session_module/gh23061-abort.phpt b/ext/session/tests/user_session_module/gh23061-abort.phpt new file mode 100644 index 000000000000..63d08195ee15 --- /dev/null +++ b/ext/session/tests/user_session_module/gh23061-abort.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-23061 (SessionHandler::create_sid() callback failure leaves the default handler open) +--EXTENSIONS-- +session +--FILE-- +getMessage(); +} + +/* The aborted session must not leave the default handler open for the next one */ +session_set_save_handler(new OwnStorageHandler()); +$started = session_start(); +session_write_close(); + +echo $message, "\n"; +var_dump($started); +?> +--EXPECTF-- +Warning: SessionHandler::read(): Parent session handler is not open in %s on line %d + +Warning: session_start(): Failed to read session data: user (path: ) in %s on line %d +Error: Session id must be a string +bool(false)