diff options
author | Gwynne Raskind <gwynne@php.net> | 2008-03-07 23:20:32 +0000 |
---|---|---|
committer | Gwynne Raskind <gwynne@php.net> | 2008-03-07 23:20:32 +0000 |
commit | 3e99d5cc5b1c3f47e3c65d39d73cdd1943d9782f (patch) | |
tree | 5cbee476f2e7bb40e76753bbfe48d559b61c4592 | |
parent | 278b7f2bdd51122e32b519f6703fbf32e0635dd2 (diff) | |
download | php-git-3e99d5cc5b1c3f47e3c65d39d73cdd1943d9782f.tar.gz |
MFH: fix bug #32330 (session_destroy, "Failed to initialize storage module", custom session handler)
-rw-r--r-- | ext/session/mod_user.c | 30 | ||||
-rw-r--r-- | ext/session/mod_user.h | 12 | ||||
-rw-r--r-- | ext/session/php_session.h | 11 | ||||
-rw-r--r-- | ext/session/session.c | 25 |
4 files changed, 49 insertions, 29 deletions
diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c index 78e494f965..861c34c214 100644 --- a/ext/session/mod_user.c +++ b/ext/session/mod_user.c @@ -70,14 +70,17 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC) return retval; } -#define STDVARS \ +#define STDVARS1 \ zval *retval; \ - int ret = FAILURE; \ - ps_user *mdata = PS_GET_MOD_DATA(); \ + int ret = FAILURE + +#define STDVARS \ + STDVARS1; \ + char *mdata = PS_GET_MOD_DATA(); \ if (!mdata) \ return FAILURE -#define PSF(a) mdata->name.ps_##a +#define PSF(a) PS(mod_user_names).name.ps_##a #define FINISH \ if (retval) { \ @@ -90,27 +93,32 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC) PS_OPEN_FUNC(user) { zval *args[2]; - STDVARS; + static char dummy = 0; + STDVARS1; SESS_ZVAL_STRING(save_path, args[0]); SESS_ZVAL_STRING(session_name, args[1]); retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC); + if (retval) { + /* This is necessary to fool the session module. Yes, it's safe to + * use a static. Neither mod_user nor the session module itself will + * ever touch this pointer. It could be set to 0xDEADBEEF for all the + * difference it makes, but for the sake of paranoia it's set to some + * valid value. + */ + PS_SET_MOD_DATA(&dummy); + } FINISH; } PS_CLOSE_FUNC(user) { - int i; - STDVARS; + STDVARS1; retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC); - for (i = 0; i < 6; i++) - zval_ptr_dtor(&mdata->names[i]); - efree(mdata); - PS_SET_MOD_DATA(NULL); FINISH; diff --git a/ext/session/mod_user.h b/ext/session/mod_user.h index c245ff9f26..628aa55b13 100644 --- a/ext/session/mod_user.h +++ b/ext/session/mod_user.h @@ -21,18 +21,6 @@ #ifndef MOD_USER_H #define MOD_USER_H -typedef union { - zval *names[6]; - struct { - zval *ps_open; - zval *ps_close; - zval *ps_read; - zval *ps_write; - zval *ps_destroy; - zval *ps_gc; - } name; -} ps_user; - extern ps_module ps_mod_user; #define ps_user_ptr &ps_mod_user diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 8896f58eab..9ecef8b16b 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -112,6 +112,17 @@ typedef struct _php_ps_globals { long gc_maxlifetime; int module_number; long cache_expire; + union { + zval *names[6]; + struct { + zval *ps_open; + zval *ps_close; + zval *ps_read; + zval *ps_write; + zval *ps_destroy; + zval *ps_gc; + } name; + } mod_user_names; zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ zend_bool bug_compat_warn; /* Whether to warn about it */ const struct ps_serializer_struct *serializer; diff --git a/ext/session/session.c b/ext/session/session.c index 2724b36cfe..9727541a0f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1489,7 +1489,6 @@ PHP_FUNCTION(session_set_save_handler) { zval **args[6]; int i; - ps_user *mdata; char *name; if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE) @@ -1509,14 +1508,13 @@ PHP_FUNCTION(session_set_save_handler) zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); - mdata = emalloc(sizeof(*mdata)); - for (i = 0; i < 6; i++) { + if (PS(mod_user_names).names[i] != NULL) { + zval_ptr_dtor(&PS(mod_user_names).names[i]); + } Z_ADDREF_PP(args[i]); - mdata->names[i] = *args[i]; + PS(mod_user_names).names[i] = *args[i]; } - - PS(mod_data) = (void *) mdata; RETURN_TRUE; } @@ -1870,6 +1868,7 @@ static void php_rinit_session_globals(TSRMLS_D) PS(id) = NULL; PS(session_status) = php_session_none; PS(mod_data) = NULL; + /* Do NOT init PS(mod_user_names) here! */ PS(http_session_vars) = NULL; } @@ -1879,6 +1878,7 @@ static void php_rshutdown_session_globals(TSRMLS_D) zval_ptr_dtor(&PS(http_session_vars)); PS(http_session_vars) = NULL; } + /* Do NOT destroy PS(mod_user_names) here! */ if (PS(mod_data)) { zend_try { PS(mod)->s_close(&PS(mod_data) TSRMLS_CC); @@ -1935,8 +1935,16 @@ PHP_FUNCTION(session_write_close) PHP_RSHUTDOWN_FUNCTION(session) { + int i; + php_session_flush(TSRMLS_C); php_rshutdown_session_globals(TSRMLS_C); + /* this should NOT be done in php_rshutdown_session_globals() */ + for (i = 0; i < 6; i++) { + if (PS(mod_user_names).names[i] != NULL) { + zval_ptr_dtor(&PS(mod_user_names).names[i]); + } + } return SUCCESS; } @@ -1944,12 +1952,17 @@ PHP_RSHUTDOWN_FUNCTION(session) static PHP_GINIT_FUNCTION(ps) { + int i; + ps_globals->save_path = NULL; ps_globals->session_name = NULL; ps_globals->id = NULL; ps_globals->mod = NULL; ps_globals->mod_data = NULL; ps_globals->session_status = php_session_none; + for (i = 0; i < 6; i++) { + ps_globals->mod_user_names.names[i] = NULL; + } ps_globals->http_session_vars = NULL; } |