Commit 5ede5b163e9 for php
commit 5ede5b163e96fed8110fd371eef8bce83e41b54f
Merge: bd53a711ac5 f2a7cb81a69
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Tue Oct 13 14:35:55 2026 -0400
Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
ext/session: do not reuse session state a save handler tore down
diff --cc ext/session/session.c
index 0ee8c94cf33,cf42be929c4..701f15309e4
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@@ -2403,23 -2397,26 +2403,29 @@@ 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);
+ zend_string_release_ex(PS(session_vars), false);
PS(session_vars) = NULL;
}
- zend_string_release_ex(PS(id), 0);
+ zend_string_release_ex(PS(id), false);
PS(id) = NULL;
- if (PS(mod)->s_open(&PS(mod_data), ZSTR_VAL(PS(save_path)), ZSTR_VAL(PS(session_name))) == FAILURE) {
+ /* Open session handler first */
+ const zend_result open_status = PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name));
+ /* NOTE: PS(mod_data) might be null if the session is a custom userland session handler */
+ if (open_status == FAILURE) {
PS(session_status) = php_session_none;
if (!EG(exception)) {
- zend_throw_error(NULL, "Failed to open session: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path)));
+ zend_throw_error(NULL, "Failed to open session: %s (path: %pS)", PS(mod)->s_name, PS(save_path));
}
RETURN_THROWS();
}
diff --cc ext/session/tests/user_session_module/session_regenerate_id_handler_closes_session.phpt
index 00000000000,b5cef21413f..80b4471d60f
mode 000000,100644..100644
--- 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
@@@ -1,0 -1,65 +1,73 @@@
+ --TEST--
+ session_regenerate_id() when the close handler destroys the session
+ --INI--
+ session.gc_probability=0
+ --EXTENSIONS--
+ session
+ --FILE--
+ <?php
+
+ ob_start();
+
+ class MySessionHandler implements SessionHandlerInterface
+ {
+ private bool $destroyed = false;
+
+ public function open(string $path, string $name): bool
+ {
+ return true;
+ }
+
+ public function close(): bool
+ {
+ if (!$this->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: Class MySessionHandler implementing SessionHandlerInterface is missing the create_sid() method which will be required in PHP 9.0 in %s on line %d
++
++Warning: Class MySessionHandler implementing SessionHandlerInterface is missing the validateId() method which will be required in PHP 9.0 in %s on line %d
++
++Deprecated: session_set_save_handler(): Providing an object to argument #1 ($sessionhandler) which does not have the create_sid() method defined is deprecated in %s on line %d
++
++Deprecated: session_set_save_handler(): Providing an object to argument #1 ($sessionhandler) which does not have the validateId() method defined is deprecated in %s on line %d
++
+ 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)