diff --git a/ext/session/session.c b/ext/session/session.c index ba71d709a536..9105b7c6b273 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2408,8 +2408,14 @@ PHP_FUNCTION(session_regenerate_id) RETURN_FALSE; } } + PS(mod)->s_close(&PS(mod_data)); + if (PS(session_status) != php_session_active) { + php_error_docref(NULL, E_WARNING, "Session ID cannot be regenerated because the save handler closed the session"); + RETURN_FALSE; + } + /* New session data */ if (PS(session_vars)) { zend_string_release_ex(PS(session_vars), 0); diff --git a/ext/session/tests/user_session_module/session_regenerate_id_handler_closes_session.phpt b/ext/session/tests/user_session_module/session_regenerate_id_handler_closes_session.phpt new file mode 100644 index 000000000000..d4908502f0ca --- /dev/null +++ b/ext/session/tests/user_session_module/session_regenerate_id_handler_closes_session.phpt @@ -0,0 +1,67 @@ +--TEST-- +session_regenerate_id() when the close handler destroys the session +--INI-- +session.save_handler=files +session.name=PHPSESSID +session.gc_probability=0 +--EXTENSIONS-- +session +--FILE-- +destroyed) { + $this->destroyed = true; + session_destroy(); + } + return true; + } + + public function read(string $id): string|false + { + return ''; + } + + public function write(string $id, string $data): bool + { + return true; + } + + public function destroy(string $id): bool + { + return true; + } + + public function gc(int $max_lifetime): int|false + { + return 0; + } +} + +session_set_save_handler(new MySessionHandler(), true); +session_start(); + +var_dump(session_regenerate_id(false)); +var_dump(session_status() === PHP_SESSION_NONE); + +?> +--EXPECTF-- +Warning: session_destroy(): Cannot call session save handler in a recursive manner in %s on line %d + +Warning: session_destroy(): Session object destruction failed in %s on line %d + +Warning: session_regenerate_id(): Session ID cannot be regenerated because the save handler closed the session in %s on line %d +bool(false) +bool(true) diff --git a/ext/session/tests/user_session_module/session_regenerate_id_handler_destroys_session.phpt b/ext/session/tests/user_session_module/session_regenerate_id_handler_destroys_session.phpt new file mode 100644 index 000000000000..ae0fcfd8b7b2 --- /dev/null +++ b/ext/session/tests/user_session_module/session_regenerate_id_handler_destroys_session.phpt @@ -0,0 +1,37 @@ +--TEST-- +session_regenerate_id() when the save handler destroys the session +--INI-- +session.save_handler=files +session.name=PHPSESSID +session.gc_probability=0 +--EXTENSIONS-- +session +--FILE-- + +--EXPECTF-- +Warning: session_destroy(): Cannot call session save handler in a recursive manner in %s on line %d + +Warning: session_destroy(): Session object destruction failed in %s on line %d + +Warning: session_regenerate_id(): Session ID cannot be regenerated because the save handler closed the session in %s on line %d +bool(false) +bool(true)