sas Wed Oct 2 23:23:02 2002 EDT Modified files: /php4/ext/session php_session.h session.c Log: Nuke PS(vars), we keep the state of registered session variables now completely in PS(http_session_vars). This avoids bugs which are caused by a lack of synchronization between the two hashes. We also don't need to worry about prioritizing one of them. Add session.bug_compat_42 and session.bug_compat_warn which are enabled by default. The logic behind bug_compat_42: IF bug_compat_42 is on, and IF register_globals is off, and IF any value of $_SESSION["key"] is NULL, and IF there is a global variable $key, then $_SESSION["key"] is set to $key. The extension emits this warning once per script, unless told otherwise. "Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn.
Index: php4/ext/session/php_session.h diff -u php4/ext/session/php_session.h:1.82 php4/ext/session/php_session.h:1.83 --- php4/ext/session/php_session.h:1.82 Tue Oct 1 07:59:45 2002 +++ php4/ext/session/php_session.h Wed Oct 2 23:23:02 2002 @@ -103,12 +103,13 @@ zend_bool cookie_secure; ps_module *mod; void *mod_data; - HashTable vars; php_session_status session_status; long gc_probability; long gc_maxlifetime; int module_number; long cache_expire; + long bug_compat; /* Whether to behave like PHP 4.2 and earlier */ + long bug_compat_warn; /* Whether to warn about it */ const struct ps_serializer_struct *serializer; zval *http_session_vars; zend_bool auto_start; @@ -188,14 +189,12 @@ PHPAPI void php_session_start(TSRMLS_D); #define PS_ADD_VARL(name,namelen) do { \ - zend_hash_add_empty_element(&PS(vars), name, namelen + 1); \ php_add_session_var(name, namelen TSRMLS_CC); \ } while (0) #define PS_ADD_VAR(name) PS_ADD_VARL(name, strlen(name)) #define PS_DEL_VARL(name,namelen) do { \ - zend_hash_del(&PS(vars), name, namelen+1); \ if (PS(http_session_vars)) { \ zend_hash_del(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1); \ } \ @@ -210,7 +209,7 @@ #define PS_ENCODE_LOOP(code) \ { \ - HashTable *_ht = (PS(http_session_vars) ? Z_ARRVAL_P(PS(http_session_vars)) : &PS(vars)); \ + HashTable *_ht = Z_ARRVAL_P(PS(http_session_vars)); \ \ for (zend_hash_internal_pointer_reset(_ht); \ zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, NULL) == HASH_KEY_IS_STRING; \ Index: php4/ext/session/session.c diff -u php4/ext/session/session.c:1.324 php4/ext/session/session.c:1.325 --- php4/ext/session/session.c:1.324 Wed Oct 2 17:51:32 2002 +++ php4/ext/session/session.c Wed Oct 2 23:23:02 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: session.c,v 1.324 2002/10/02 21:51:32 sas Exp $ */ +/* $Id: session.c,v 1.325 2002/10/03 03:23:02 sas Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -121,6 +121,8 @@ /* {{{ PHP_INI */ PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("session.bug_compat_42", "1", PHP_INI_ALL, +OnUpdateBool, bug_compat, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.bug_compat_warn", "1", PHP_INI_ALL, +OnUpdateBool, bug_compat_warn, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.save_path", "/tmp", PHP_INI_ALL, OnUpdateString, save_path, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateString, session_name, php_ps_globals, ps_globals) PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler) @@ -163,6 +165,9 @@ ps_user_ptr }; +#define IF_SESSION_VARS() \ + if (PS(http_session_vars) && PS(http_session_vars)->type == IS_ARRAY) + PHPAPI int php_session_register_serializer(const char *name, int (*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)) @@ -305,14 +310,14 @@ } else { zend_set_hash_symbol(state_val, name, namelen, 1, 2, Z_ARRVAL_P(PS(http_session_vars)), &EG(symbol_table)); } - } else if (PS(http_session_vars)) { + } else IF_SESSION_VARS() { zend_set_hash_symbol(state_val, name, namelen, 0, 1, Z_ARRVAL_P(PS(http_session_vars))); } } int php_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) { - if (PS(http_session_vars) && PS(http_session_vars)->type == IS_ARRAY) { + IF_SESSION_VARS() { return zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, (void **) state_var); } @@ -483,14 +488,13 @@ { char *ret = NULL; - if (!PS(http_session_vars)) { + IF_SESSION_VARS() { + if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) + ret = NULL; + } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot encode non-existent session."); - return NULL; } - if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) - ret = NULL; - return ret; } @@ -586,33 +590,66 @@ } } -static void php_session_save_current_state(TSRMLS_D) +static void migrate_global(HashTable *ht, HashPosition *pos TSRMLS_DC) { - char *val; - int vallen; - int ret = FAILURE; - char *variable; - uint variable_len; + char *str; + uint str_len; ulong num_key; - HashPosition pos; + int n; + zval **val = NULL; - if (!PG(register_globals) && !PS(http_session_vars)) { - return; - } - - if (PS(http_session_vars) && PS(http_session_vars)->type != IS_ARRAY) { - return; + n = zend_hash_get_current_key_ex(ht, &str, &str_len, &num_key, 0, pos); + + switch (n) { + case HASH_KEY_IS_STRING: + zend_hash_find(&EG(symbol_table), str, str_len, (void **) +&val); + if (val) { + ZEND_SET_SYMBOL_WITH_LENGTH(ht, str, str_len, *val, 1, +0); + } + break; + case HASH_KEY_IS_LONG: + php_error(E_NOTICE, "The session bug compatibility code will +not " + "try to locate the global variable $%d due to +its " + "numeric nature.", num_key); + break; } - - if (PS(http_session_vars)) { - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(PS(http_session_vars)), &pos); - zend_hash_get_current_key_ex(Z_ARRVAL_P(PS(http_session_vars)), &variable, &variable_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING; - zend_hash_move_forward_ex(Z_ARRVAL_P(PS(http_session_vars)),&pos)) { - PS_ADD_VARL(variable, variable_len-1); +} + +static void php_session_save_current_state(TSRMLS_D) +{ + int ret = FAILURE; + + IF_SESSION_VARS() { + if (PS(bug_compat) && !PG(register_globals)) { + HashTable *ht = Z_ARRVAL_P(PS(http_session_vars)); + HashPosition pos; + zval **val; + int do_warn = 0; + + zend_hash_internal_pointer_reset_ex(ht, &pos); + + while (zend_hash_get_current_data_ex(ht, + (void **) &val, &pos) != FAILURE) { + if (Z_TYPE_PP(val) == IS_NULL) { + do_warn = 1; + + migrate_global(ht, &pos); + } + zend_hash_move_forward_ex(ht, &pos); + } + + if (do_warn && PS(bug_compat_warn)) { + php_error(E_WARNING, "Your script possibly relies on a +session side-effect which existed until PHP 4.2.3. Please be advised that the session +extension does not consider global variables as a source of data, unless +register_globals is enabled. You can disable this functionality and this warning by +setting session.bug_compat_42 or session.bug_compat_warn."); + } } + } else { + return; } if (PS(mod_data)) { + char *val; + int vallen; + val = php_session_encode(&vallen TSRMLS_CC); if (val) { ret = PS(mod)->write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); @@ -1328,11 +1365,17 @@ convert_to_string_ex(p_name); - if (zend_hash_find(&PS(vars), Z_STRVAL_PP(p_name), - Z_STRLEN_PP(p_name)+1, (void **)&p_var) == SUCCESS) - RETURN_TRUE - else + if (PS(session_status) == php_session_none) RETURN_FALSE; + + IF_SESSION_VARS() { + if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), + Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name)+1, + (void **)&p_var) == SUCCESS) { + RETURN_TRUE; + } + } + RETURN_FALSE; } /* }}} */ @@ -1402,25 +1445,30 @@ Unset all registered variables */ PHP_FUNCTION(session_unset) { - zval **tmp; - char *variable; - ulong num_key; - if (PS(session_status) == php_session_none) RETURN_FALSE; - if (PG(register_globals)) { - for (zend_hash_internal_pointer_reset(&PS(vars)); - zend_hash_get_current_key(&PS(vars), &variable, &num_key, 0) == HASH_KEY_IS_STRING; - zend_hash_move_forward(&PS(vars))) { - if (zend_hash_find(&EG(symbol_table), variable, strlen(variable) + 1, (void **) &tmp) - == SUCCESS) - zend_hash_del(&EG(symbol_table), variable, strlen(variable) + 1); + IF_SESSION_VARS() { + HashTable *ht = Z_ARRVAL_P(PS(http_session_vars)); + + if (PG(register_globals)) { + uint str_len; + char *str; + ulong num_key; + HashPosition pos; + + zend_hash_internal_pointer_reset_ex(ht, &pos); + + while (zend_hash_get_current_key_ex(ht, &str, &str_len, +&num_key, + 0, &pos) == HASH_KEY_IS_STRING) { + zend_hash_del(&EG(symbol_table), str, str_len); + zend_hash_move_forward_ex(ht, &pos); + } } + + /* Clean $_SESSION. */ + zend_hash_clean(ht); } - - /* Clean $HTTP_SESSION_VARS. */ - zend_hash_clean(Z_ARRVAL_P(PS(http_session_vars))); } /* }}} */ @@ -1433,7 +1481,6 @@ static void php_rinit_session_globals(TSRMLS_D) { - zend_hash_init(&PS(vars), 0, NULL, NULL, 0); PS(id) = NULL; PS(session_status) = php_session_none; PS(mod_data) = NULL; @@ -1448,7 +1495,6 @@ if (PS(id)) { efree(PS(id)); } - zend_hash_destroy(&PS(vars)); }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php