diff options
Diffstat (limited to 'ext/session/session.c')
-rw-r--r-- | ext/session/session.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/ext/session/session.c b/ext/session/session.c index 5b7841de5c..6fd0ee2f37 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -97,11 +97,13 @@ zend_class_entry *php_session_update_timestamp_iface_entry; #define APPLY_TRANS_SID (PS(use_trans_sid) && !PS(use_only_cookies)) static void php_session_send_cookie(void); +static void php_session_abort(void); /* Dispatched by RINIT and by php_session_destroy */ static inline void php_rinit_session_globals(void) /* {{{ */ { /* Do NOT init PS(mod_user_names) here! */ + /* TODO: These could be moved to MINIT and removed. These should be initialized by php_rshutdown_session_globals() always when execution is finished. */ PS(id) = NULL; PS(session_status) = php_session_none; PS(mod_data) = NULL; @@ -129,10 +131,15 @@ static inline void php_rshutdown_session_globals(void) /* {{{ */ zend_string_release(PS(id)); PS(id) = NULL; } + if (PS(session_vars)) { zend_string_release(PS(session_vars)); PS(session_vars) = NULL; } + + /* User save handlers may end up directly here by misuse, bugs in user script, etc. */ + /* Set session status to prevent error while restoring save handler INI value. */ + PS(session_status) = php_session_none; } /* }}} */ @@ -489,11 +496,6 @@ static void php_session_gc(void) /* {{{ */ nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg()); if (nrand < PS(gc_probability)) { PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels); -#ifdef SESSION_DEBUG - if (nrdels != -1) { - php_error_docref(NULL, E_NOTICE, "purged %d expired session objects", nrdels); - } -#endif } } } /* }}} */ @@ -502,7 +504,10 @@ static void php_session_initialize(void) /* {{{ */ { zend_string *val = NULL; + PS(session_status) = php_session_active; + if (!PS(mod)) { + PS(session_status) = php_session_disabled; php_error_docref(NULL, E_ERROR, "No storage module chosen - failed to initialize session"); return; } @@ -511,14 +516,19 @@ static void php_session_initialize(void) /* {{{ */ if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE /* || PS(mod_data) == NULL */ /* FIXME: open must set valid PS(mod_data) with success */ ) { + php_session_abort(); php_error_docref(NULL, E_ERROR, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path)); return; } /* If there is no ID, use session module to create one */ - if (!PS(id)) { + if (!PS(id) || !ZSTR_VAL(PS(id))[0]) { + if (PS(id)) { + zend_string_release(PS(id)); + } PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { + php_session_abort(); php_error_docref(NULL, E_ERROR, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); return; } @@ -540,16 +550,15 @@ static void php_session_initialize(void) /* {{{ */ } php_session_reset_id(); - PS(session_status) = php_session_active; /* Read data */ php_session_track_init(); if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, PS(gc_maxlifetime)) == FAILURE) { + php_session_abort(); /* Some broken save handler implementation returns FAILURE for non-existent session ID */ /* It's better to raise error for this, but disabled error for better compatibility */ - /* - php_error_docref(NULL, E_NOTICE, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path)); - */ + php_error_docref(NULL, E_WARNING, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + return; } /* GC must be done after read */ @@ -597,11 +606,16 @@ static void php_session_save_current_state(int write) /* {{{ */ } if ((ret == FAILURE) && !EG(exception)) { - php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please " - "verify that the current setting of session.save_path " - "is correct (%s)", - PS(mod)->s_name, - PS(save_path)); + if (!PS(mod_user_implemented)) { + php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please " + "verify that the current setting of session.save_path " + "is correct (%s)", + PS(mod)->s_name, + PS(save_path)); + } else { + php_error_docref(NULL, E_WARNING, "Failed to write session data using user " + "defined save handler. (session.save_path: %s)", PS(save_path)); + } } } } @@ -1123,7 +1137,7 @@ static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PHPAPI int php_session_register_serializer(const char *name, zend_string *(*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)) /* {{{ */ { - int ret = -1; + int ret = FAILURE; int i; for (i = 0; i < MAX_SERIALIZERS; i++) { @@ -1132,7 +1146,7 @@ PHPAPI int php_session_register_serializer(const char *name, zend_string *(*enco ps_serializers[i].encode = encode; ps_serializers[i].decode = decode; ps_serializers[i + 1].name = NULL; - ret = 0; + ret = SUCCESS; break; } } @@ -1154,13 +1168,13 @@ static ps_module *ps_modules[MAX_MODULES + 1] = { PHPAPI int php_session_register_module(ps_module *ptr) /* {{{ */ { - int ret = -1; + int ret = FAILURE; int i; for (i = 0; i < MAX_MODULES; i++) { if (!ps_modules[i]) { ps_modules[i] = ptr; - ret = 0; + ret = SUCCESS; break; } } @@ -1309,11 +1323,13 @@ static int php_session_cache_limiter(void) /* {{{ */ php_session_cache_limiter_t *lim; if (PS(cache_limiter)[0] == '\0') return 0; + if (PS(session_status) != php_session_active) return -1; if (SG(headers_sent)) { const char *output_start_filename = php_output_get_start_filename(); int output_start_lineno = php_output_get_start_lineno(); + php_session_abort(); if (output_start_filename) { php_error_docref(NULL, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno); } else { @@ -1681,8 +1697,8 @@ PHPAPI void php_session_start(void) /* {{{ */ static void php_session_flush(int write) /* {{{ */ { if (PS(session_status) == php_session_active) { - PS(session_status) = php_session_none; php_session_save_current_state(write); + PS(session_status) = php_session_none; } } /* }}} */ @@ -1690,10 +1706,10 @@ static void php_session_flush(int write) /* {{{ */ static void php_session_abort(void) /* {{{ */ { if (PS(session_status) == php_session_active) { - PS(session_status) = php_session_none; if (PS(mod_data) || PS(mod_user_implemented)) { PS(mod)->s_close(&PS(mod_data)); } + PS(session_status) = php_session_none; } } /* }}} */ @@ -2068,13 +2084,13 @@ static PHP_FUNCTION(session_regenerate_id) return; } - if (SG(headers_sent) && PS(use_cookies)) { - php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent"); + if (PS(session_status) != php_session_active) { + php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active"); RETURN_FALSE; } - if (PS(session_status) != php_session_active) { - php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active"); + if (SG(headers_sent) && PS(use_cookies)) { + php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent"); RETURN_FALSE; } @@ -2110,15 +2126,18 @@ static PHP_FUNCTION(session_regenerate_id) PS(session_vars) = NULL; } zend_string_release(PS(id)); - PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); - if (!PS(id)) { + PS(id) = NULL; + + if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { PS(session_status) = php_session_none; - php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to open session: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; } - if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { + + PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); + if (!PS(id)) { PS(session_status) = php_session_none; - php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create(open) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; } if (PS(use_strict_mode) && PS(mod)->s_validate_sid && @@ -2126,6 +2145,7 @@ static PHP_FUNCTION(session_regenerate_id) zend_string_release(PS(id)); PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { + PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; @@ -2133,6 +2153,7 @@ static PHP_FUNCTION(session_regenerate_id) } /* Read is required to make new session data at this point. */ if (PS(mod)->s_read(&PS(mod_data), PS(id), &data, PS(gc_maxlifetime)) == FAILURE) { + PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create(read) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; @@ -2304,11 +2325,6 @@ static PHP_FUNCTION(session_start) RETURN_FALSE; } - if (PS(id) && !(ZSTR_LEN(PS(id)))) { - php_error_docref(NULL, E_WARNING, "Cannot start session with empty session ID"); - RETURN_FALSE; - } - /* set options */ if (options) { ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), num_idx, str_idx, value) { |