Commit a8bdfa665b7 for php.net
commit a8bdfa665b7a2d0027eed7954f0a0599d7d432e4
Author: Gina Peter Banyard <girgias@php.net>
Date: Thu Feb 5 21:23:42 2026 +0000
ext/session: remove mod_user_class_name global
diff --git a/ext/session/php_session.h b/ext/session/php_session.h
index 9bf97cca02b..ace8c6998cd 100644
--- a/ext/session/php_session.h
+++ b/ext/session/php_session.h
@@ -174,7 +174,6 @@ typedef struct _php_ps_globals {
zval ps_validate_sid;
zval ps_update_timestamp;
} mod_user_names;
- zend_string *mod_user_class_name;
bool mod_user_implemented;
bool mod_user_is_open;
bool auto_start;
diff --git a/ext/session/session.c b/ext/session/session.c
index 7578a038ead..1bb2f3a80b6 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -177,11 +177,6 @@ static void php_rshutdown_session_globals(void)
PS(session_vars) = NULL;
}
- if (PS(mod_user_class_name)) {
- zend_string_release(PS(mod_user_class_name));
- PS(mod_user_class_name) = NULL;
- }
-
php_session_cleanup_filename();
/* User save handlers may end up directly here by misuse, bugs in user script, etc. */
@@ -516,9 +511,7 @@ static void php_session_save_current_state(bool write)
if (write) {
IF_SESSION_VARS() {
- zend_string *handler_class_name = PS(mod_user_class_name);
- const char *handler_function_name = "write";
-
+ zval *handler_function = &PS(mod_user_names).ps_write;
if (PS(mod_data) || PS(mod_user_implemented)) {
zend_string *val;
@@ -530,7 +523,7 @@ static void php_session_save_current_state(bool write)
&& zend_string_equals(val, PS(session_vars))
) {
ret = PS(mod)->s_update_timestamp(&PS(mod_data), PS(id), val, PS(gc_maxlifetime));
- handler_function_name = handler_class_name != NULL ? "updateTimestamp" : "update_timestamp";
+ handler_function = &PS(mod_user_names).ps_update_timestamp;
} else {
ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, PS(gc_maxlifetime));
}
@@ -547,14 +540,12 @@ static void php_session_save_current_state(bool write)
"is correct (%s)",
PS(mod)->s_name,
ZSTR_VAL(PS(save_path)));
- } else if (handler_class_name != NULL) {
- php_error_docref(NULL, E_WARNING, "Failed to write session data using user "
- "defined save handler. (session.save_path: %s, handler: %s::%s)", ZSTR_VAL(PS(save_path)),
- ZSTR_VAL(handler_class_name), handler_function_name);
} else {
+ zend_string *callable_name = zend_get_callable_name(handler_function);
php_error_docref(NULL, E_WARNING, "Failed to write session data using user "
"defined save handler. (session.save_path: %s, handler: %s)", ZSTR_VAL(PS(save_path)),
- handler_function_name);
+ ZSTR_VAL(callable_name));
+ zend_string_release_ex(callable_name, false);
}
}
}
@@ -2115,11 +2106,6 @@ PHP_FUNCTION(session_set_save_handler)
RETURN_FALSE;
}
- if (PS(mod_user_class_name)) {
- zend_string_release(PS(mod_user_class_name));
- }
- PS(mod_user_class_name) = zend_string_copy(Z_OBJCE_P(obj)->name);
-
/* Define mandatory handlers */
SESSION_SET_USER_HANDLER_OO_MANDATORY(ps_open, "open");
SESSION_SET_USER_HANDLER_OO_MANDATORY(ps_close, "close");
@@ -2154,7 +2140,8 @@ PHP_FUNCTION(session_set_save_handler)
/* Validate ID handler */
SESSION_SET_USER_HANDLER_OO(ps_validate_sid, zend_string_copy(validate_sid_name));
/* Update Timestamp handler */
- SESSION_SET_USER_HANDLER_OO(ps_update_timestamp, zend_string_copy(update_timestamp_name));
+ /* We need to provide a new string with the correct casing so that error messages work */
+ SESSION_SET_USER_HANDLER_OO(ps_update_timestamp, ZSTR_INIT_LITERAL("updateTimestamp", false));
} else {
/* For BC reasons we accept methods even if the class does not implement the interface */
if (zend_hash_find_ptr(object_methods, validate_sid_name)) {
@@ -2163,7 +2150,8 @@ PHP_FUNCTION(session_set_save_handler)
}
if (zend_hash_find_ptr(object_methods, update_timestamp_name)) {
/* For BC reasons we accept methods even if the class does not implement the interface */
- SESSION_SET_USER_HANDLER_OO(ps_update_timestamp, zend_string_copy(update_timestamp_name));
+ /* We need to provide a new string with the correct casing so that error messages work */
+ SESSION_SET_USER_HANDLER_OO(ps_update_timestamp, ZSTR_INIT_LITERAL("updateTimestamp", false));
}
}
zend_string_release_ex(validate_sid_name, false);
@@ -2240,12 +2228,6 @@ PHP_FUNCTION(session_set_save_handler)
RETURN_FALSE;
}
- /* If a custom session handler is already set, release relevant info */
- if (PS(mod_user_class_name)) {
- zend_string_release(PS(mod_user_class_name));
- PS(mod_user_class_name) = NULL;
- }
-
/* remove shutdown function */
remove_user_shutdown_function("session_shutdown", strlen("session_shutdown"));
@@ -2906,7 +2888,6 @@ static PHP_GINIT_FUNCTION(ps)
ps_globals->session_status = php_session_none;
ps_globals->default_mod = NULL;
ps_globals->mod_user_implemented = false;
- ps_globals->mod_user_class_name = NULL;
ps_globals->mod_user_is_open = false;
ps_globals->session_vars = NULL;
ps_globals->set_handler = false;
diff --git a/ext/session/tests/user_session_module/gh7787.phpt b/ext/session/tests/user_session_module/gh7787.phpt
index 85ce7bd887c..ee62e8f0496 100644
--- a/ext/session/tests/user_session_module/gh7787.phpt
+++ b/ext/session/tests/user_session_module/gh7787.phpt
@@ -84,6 +84,6 @@ public function updateTimestamp($sessid, $sessdata): bool {
Deprecated: session_set_save_handler(): Providing individual callbacks instead of an object implementing SessionHandlerInterface is deprecated in %s on line %d
-Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: %S, handler: write) in %s on line %d
+Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: %S, handler: {closure:%s:57}) in %s on line %d
-Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: %S, handler: update_timestamp) in %s on line %d
+Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: %S, handler: {closure:%s:62}) in %s on line %d