summaryrefslogtreecommitdiff
path: root/ext/session/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/session/session.c')
-rw-r--r--ext/session/session.c470
1 files changed, 346 insertions, 124 deletions
diff --git a/ext/session/session.c b/ext/session/session.c
index d702d1b159..c51d51b46f 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -94,10 +94,16 @@ zend_class_entry *php_session_update_timestamp_iface_entry;
return FAILURE; \
}
+#define SESSION_CHECK_OUTPUT_STATE \
+ if (SG(headers_sent) && stage != ZEND_INI_STAGE_DEACTIVATE) { \
+ php_error_docref(NULL, E_WARNING, "Headers already sent. You cannot change the session module's ini settings at this time"); \
+ return FAILURE; \
+ }
+
#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);
+static int php_session_send_cookie(void);
+static int php_session_abort(void);
/* Dispatched by RINIT and by php_session_destroy */
static inline void php_rinit_session_globals(void) /* {{{ */
@@ -107,6 +113,7 @@ static inline void php_rinit_session_globals(void) /* {{{ */
PS(id) = NULL;
PS(session_status) = php_session_none;
PS(in_save_handler) = 0;
+ PS(set_handler) = 0;
PS(mod_data) = NULL;
PS(mod_user_is_open) = 0;
PS(define_sid) = 1;
@@ -144,7 +151,7 @@ static inline void php_rshutdown_session_globals(void) /* {{{ */
}
/* }}} */
-static int php_session_destroy(void) /* {{{ */
+PHPAPI int php_session_destroy(void) /* {{{ */
{
int retval = SUCCESS;
@@ -370,7 +377,7 @@ static zend_long php_session_gc(zend_bool immediate) /* {{{ */
return num;
} /* }}} */
-static void php_session_initialize(void) /* {{{ */
+static int php_session_initialize(void) /* {{{ */
{
zend_string *val = NULL;
@@ -378,8 +385,8 @@ static void php_session_initialize(void) /* {{{ */
if (!PS(mod)) {
PS(session_status) = php_session_disabled;
- php_error_docref(NULL, E_ERROR, "No storage module chosen - failed to initialize session");
- return;
+ php_error_docref(NULL, E_WARNING, "No storage module chosen - failed to initialize session");
+ return FAILURE;
}
/* Open session handler first */
@@ -387,8 +394,8 @@ static void php_session_initialize(void) /* {{{ */
/* || 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;
+ php_error_docref(NULL, E_WARNING, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+ return FAILURE;
}
/* If there is no ID, use session module to create one */
@@ -400,7 +407,7 @@ static void php_session_initialize(void) /* {{{ */
if (!PS(id)) {
php_session_abort();
zend_throw_error(NULL, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
- return;
+ return FAILURE;
}
if (PS(use_cookies)) {
PS(send_cookie) = 1;
@@ -419,7 +426,10 @@ static void php_session_initialize(void) /* {{{ */
}
}
- php_session_reset_id();
+ if (php_session_reset_id() == FAILURE) {
+ php_session_abort();
+ return FAILURE;
+ }
/* Read data */
php_session_track_init();
@@ -427,7 +437,7 @@ static void php_session_initialize(void) /* {{{ */
php_session_abort();
/* FYI: Some broken save handlers return FAILURE for non-existent session ID, this is incorrect */
php_error_docref(NULL, E_WARNING, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path));
- return;
+ return FAILURE;
}
/* GC must be done after read */
@@ -444,6 +454,7 @@ static void php_session_initialize(void) /* {{{ */
php_session_decode(val);
zend_string_release(val);
}
+ return SUCCESS;
}
/* }}} */
@@ -518,7 +529,9 @@ static void php_session_normalize_vars() /* {{{ */
static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */
{
ps_module *tmp;
+
SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
tmp = _php_find_ps_module(ZSTR_VAL(new_value));
@@ -535,6 +548,13 @@ static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
php_error_docref(NULL, err_type, "Cannot find save handler '%s'", ZSTR_VAL(new_value));
}
+
+ return FAILURE;
+ }
+
+ /* "user" save handler should not be set by user */
+ if (!PS(set_handler) && tmp == ps_user_ptr) {
+ php_error_docref(NULL, E_RECOVERABLE_ERROR, "Cannot set 'user' save handler by ini_set() or session_module_name()");
return FAILURE;
}
@@ -548,7 +568,9 @@ static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */
static PHP_INI_MH(OnUpdateSerializer) /* {{{ */
{
const ps_serializer *tmp;
+
SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
tmp = _php_find_ps_serializer(ZSTR_VAL(new_value));
@@ -576,6 +598,7 @@ static PHP_INI_MH(OnUpdateSerializer) /* {{{ */
static PHP_INI_MH(OnUpdateTransSid) /* {{{ */
{
SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
if (!strncasecmp(ZSTR_VAL(new_value), "on", sizeof("on"))) {
PS(use_trans_sid) = (zend_bool) 1;
@@ -587,8 +610,12 @@ static PHP_INI_MH(OnUpdateTransSid) /* {{{ */
}
/* }}} */
+
static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+
/* Only do the safemode/open_basedir check at runtime */
if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) {
char *p;
@@ -613,13 +640,16 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
}
}
- OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
- return SUCCESS;
+ return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
}
/* }}} */
+
static PHP_INI_MH(OnUpdateName) /* {{{ */
{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+
/* Numeric session.name won't work at all */
if ((!ZSTR_LEN(new_value) || is_numeric_string(ZSTR_VAL(new_value), ZSTR_LEN(new_value), NULL, NULL, 0))) {
int err_type;
@@ -637,16 +667,58 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
return FAILURE;
}
- OnUpdateStringUnempty(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
- return SUCCESS;
+ return OnUpdateStringUnempty(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
}
/* }}} */
+
+static PHP_INI_MH(OnUpdateCookieLifetime) /* {{{ */
+{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+ if (atol(ZSTR_VAL(new_value)) < 0) {
+ php_error_docref(NULL, E_WARNING, "CookieLifetime cannot be negative");
+ return FAILURE;
+ }
+ return OnUpdateLongGEZero(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+/* }}} */
+
+
+static PHP_INI_MH(OnUpdateSessionLong) /* {{{ */
+{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+ return OnUpdateLong(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+/* }}} */
+
+
+static PHP_INI_MH(OnUpdateSessionString) /* {{{ */
+{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+ return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+/* }}} */
+
+
+static PHP_INI_MH(OnUpdateSessionBool) /* {{{ */
+{
+ SESSION_CHECK_OUTPUT_STATE;
+ SESSION_CHECK_ACTIVE_STATE;
+ return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+/* }}} */
+
+
static PHP_INI_MH(OnUpdateSidLength) /* {{{ */
{
zend_long val;
char *endptr = NULL;
+ SESSION_CHECK_OUTPUT_STATE;
+ SESSION_CHECK_ACTIVE_STATE;
val = ZEND_STRTOL(ZSTR_VAL(new_value), &endptr, 10);
if (endptr && (*endptr == '\0')
&& val >= 22 && val <= PS_MAX_SID_LENGTH) {
@@ -665,6 +737,8 @@ static PHP_INI_MH(OnUpdateSidBits) /* {{{ */
zend_long val;
char *endptr = NULL;
+ SESSION_CHECK_OUTPUT_STATE;
+ SESSION_CHECK_ACTIVE_STATE;
val = ZEND_STRTOL(ZSTR_VAL(new_value), &endptr, 10);
if (endptr && (*endptr == '\0')
&& val >= 4 && val <=6) {
@@ -679,6 +753,16 @@ static PHP_INI_MH(OnUpdateSidBits) /* {{{ */
/* }}} */
+static PHP_INI_MH(OnUpdateLazyWrite) /* {{{ */
+{
+ SESSION_CHECK_ACTIVE_STATE;
+ SESSION_CHECK_OUTPUT_STATE;
+ return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
+}
+/* }}} */
+
+
+
static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
{
int tmp;
@@ -702,29 +786,29 @@ static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
/* {{{ PHP_INI
*/
PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir, save_path, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals)
PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler)
- STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateLong, gc_probability, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateLong, gc_divisor, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateLong, gc_maxlifetime, php_ps_globals, ps_globals)
+ STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateSessionLong, gc_probability, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateSessionLong, gc_divisor, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateSessionLong, gc_maxlifetime, php_ps_globals, ps_globals)
PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer)
- STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateLong, cookie_lifetime, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateString, cookie_path, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateString, cookie_domain, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.cookie_secure", "", PHP_INI_ALL, OnUpdateBool, cookie_secure, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.cookie_httponly", "", PHP_INI_ALL, OnUpdateBool, cookie_httponly, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_cookies, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_only_cookies, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateBool, use_strict_mode, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateString, cache_limiter, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateLong, cache_expire, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateCookieLifetime,cookie_lifetime, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateSessionString, cookie_path, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionString, cookie_domain, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_only_cookies, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateSessionString, extern_referer_chk, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateSessionString, cache_limiter, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateSessionLong, cache_expire, php_ps_globals, ps_globals)
PHP_INI_ENTRY("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateTransSid)
PHP_INI_ENTRY("session.sid_length", "32", PHP_INI_ALL, OnUpdateSidLength)
PHP_INI_ENTRY("session.sid_bits_per_character", "4", PHP_INI_ALL, OnUpdateSidBits)
- STD_PHP_INI_BOOLEAN("session.lazy_write", "1", PHP_INI_ALL, OnUpdateBool, lazy_write, php_ps_globals, ps_globals)
+ STD_PHP_INI_BOOLEAN("session.lazy_write", "1", PHP_INI_ALL, OnUpdateLazyWrite, lazy_write, php_ps_globals, ps_globals)
/* Upload progress */
STD_PHP_INI_BOOLEAN("session.upload_progress.enabled",
@@ -810,10 +894,6 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary) /* {{{ */
smart_str_appendc(&buf, (unsigned char)ZSTR_LEN(key));
smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key));
php_var_serialize(&buf, struc, &var_hash);
- } else {
- if (ZSTR_LEN(key) > PS_BIN_MAX) continue;
- smart_str_appendc(&buf, (unsigned char) (ZSTR_LEN(key) & PS_BIN_UNDEF));
- smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key));
);
smart_str_0(&buf);
@@ -827,10 +907,10 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
{
const char *p;
const char *endptr = val + vallen;
- int has_value;
int namelen;
zend_string *name;
php_unserialize_data_t var_hash;
+ zval *current, rv;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
@@ -842,26 +922,18 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
return FAILURE;
}
- has_value = *p & PS_BIN_UNDEF ? 0 : 1;
-
name = zend_string_init(p + 1, namelen, 0);
-
p += namelen + 1;
+ current = var_tmp_var(&var_hash);
- if (has_value) {
- zval *current, rv;
- current = var_tmp_var(&var_hash);
- if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
- ZVAL_PTR(&rv, current);
- php_set_session_var(name, &rv, &var_hash);
- } else {
- zend_string_release(name);
- php_session_normalize_vars();
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- return FAILURE;
- }
+ if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
+ ZVAL_PTR(&rv, current);
+ php_set_session_var(name, &rv, &var_hash);
} else {
- PS_ADD_VARL(name);
+ zend_string_release(name);
+ php_session_normalize_vars();
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return FAILURE;
}
zend_string_release(name);
}
@@ -874,7 +946,6 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
/* }}} */
#define PS_DELIMITER '|'
-#define PS_UNDEF_MARKER '!'
PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
{
@@ -885,19 +956,14 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
PHP_VAR_SERIALIZE_INIT(var_hash);
PS_ENCODE_LOOP(
- smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key));
- if (memchr(ZSTR_VAL(key), PS_DELIMITER, ZSTR_LEN(key)) || memchr(ZSTR_VAL(key), PS_UNDEF_MARKER, ZSTR_LEN(key))) {
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
- smart_str_free(&buf);
- return NULL;
- }
- smart_str_appendc(&buf, PS_DELIMITER);
-
- php_var_serialize(&buf, struc, &var_hash);
- } else {
- smart_str_appendc(&buf, PS_UNDEF_MARKER);
- smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key));
- smart_str_appendc(&buf, PS_DELIMITER);
+ smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key));
+ if (memchr(ZSTR_VAL(key), PS_DELIMITER, ZSTR_LEN(key))) {
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+ smart_str_free(&buf);
+ return NULL;
+ }
+ smart_str_appendc(&buf, PS_DELIMITER);
+ php_var_serialize(&buf, struc, &var_hash);
);
smart_str_0(&buf);
@@ -913,8 +979,9 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
const char *endptr = val + vallen;
ptrdiff_t namelen;
zend_string *name;
- int has_value, retval = SUCCESS;
+ int retval = SUCCESS;
php_unserialize_data_t var_hash;
+ zval *current, rv;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
@@ -925,35 +992,24 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
while (*q != PS_DELIMITER) {
if (++q >= endptr) goto break_outer_loop;
}
- if (p[0] == PS_UNDEF_MARKER) {
- p++;
- has_value = 0;
- } else {
- has_value = 1;
- }
namelen = q - p;
name = zend_string_init(p, namelen, 0);
q++;
- if (has_value) {
- zval *current, rv;
- current = var_tmp_var(&var_hash);
- if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) {
- ZVAL_PTR(&rv, current);
- php_set_session_var(name, &rv, &var_hash);
- } else {
- zend_string_release(name);
- retval = FAILURE;
- goto break_outer_loop;
- }
+ current = var_tmp_var(&var_hash);
+ if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) {
+ ZVAL_PTR(&rv, current);
+ php_set_session_var(name, &rv, &var_hash);
} else {
- PS_ADD_VARL(name);
+ zend_string_release(name);
+ retval = FAILURE;
+ goto break_outer_loop;
}
zend_string_release(name);
-
p = q;
}
+
break_outer_loop:
php_session_normalize_vars();
@@ -1235,7 +1291,7 @@ static void php_session_remove_cookie(void) {
efree(session_cookie);
}
-static void php_session_send_cookie(void) /* {{{ */
+static int php_session_send_cookie(void) /* {{{ */
{
smart_str ncookie = {0};
zend_string *date_fmt = NULL;
@@ -1250,7 +1306,7 @@ static void php_session_send_cookie(void) /* {{{ */
} else {
php_error_docref(NULL, E_WARNING, "Cannot send session cookie - headers already sent");
}
- return;
+ return FAILURE;
}
/* URL encode session_name and id because they might be user supplied */
@@ -1308,6 +1364,8 @@ static void php_session_send_cookie(void) /* {{{ */
header, probably sent with setcookie() will be replaced! */
sapi_add_header_ex(estrndup(ZSTR_VAL(ncookie.s), ZSTR_LEN(ncookie.s)), ZSTR_LEN(ncookie.s), 0, 0);
smart_str_free(&ncookie);
+
+ return SUCCESS;
}
/* }}} */
@@ -1353,7 +1411,8 @@ static void ppid2sid(zval *ppid) {
}
}
-PHPAPI void php_session_reset_id(void) /* {{{ */
+
+PHPAPI int php_session_reset_id(void) /* {{{ */
{
int module_number = PS(module_number);
zval *sid, *data, *ppid;
@@ -1361,7 +1420,7 @@ PHPAPI void php_session_reset_id(void) /* {{{ */
if (!PS(id)) {
php_error_docref(NULL, E_WARNING, "Cannot set session ID - session ID is not initialized");
- return;
+ return FAILURE;
}
if (PS(use_cookies) && PS(send_cookie)) {
@@ -1418,10 +1477,12 @@ PHPAPI void php_session_reset_id(void) /* {{{ */
zend_string_release(sname);
php_url_scanner_add_session_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1);
}
+ return SUCCESS;
}
/* }}} */
-PHPAPI void php_session_start(void) /* {{{ */
+
+PHPAPI int php_session_start(void) /* {{{ */
{
zval *ppid;
zval *data;
@@ -1431,7 +1492,7 @@ PHPAPI void php_session_start(void) /* {{{ */
switch (PS(session_status)) {
case php_session_active:
php_error(E_NOTICE, "A session had already been started - ignoring session_start()");
- return;
+ return FAILURE;
break;
case php_session_disabled:
@@ -1440,7 +1501,7 @@ PHPAPI void php_session_start(void) /* {{{ */
PS(mod) = _php_find_ps_module(value);
if (!PS(mod)) {
php_error_docref(NULL, E_WARNING, "Cannot find save handler '%s' - session startup failed", value);
- return;
+ return FAILURE;
}
}
value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler") - 1, 0);
@@ -1448,14 +1509,14 @@ PHPAPI void php_session_start(void) /* {{{ */
PS(serializer) = _php_find_ps_serializer(value);
if (!PS(serializer)) {
php_error_docref(NULL, E_WARNING, "Cannot find serialization handler '%s' - session startup failed", value);
- return;
+ return FAILURE;
}
}
PS(session_status) = php_session_none;
- /* fallthrough */
+ /* Fall through */
- default:
case php_session_none:
+ default:
/* Setup internal flags */
PS(define_sid) = !PS(use_only_cookies); /* SID constant is defined when non-cookie ID is used */
PS(send_cookie) = PS(use_cookies) || PS(use_only_cookies);
@@ -1531,36 +1592,50 @@ PHPAPI void php_session_start(void) /* {{{ */
PS(id) = NULL;
}
- php_session_initialize();
- php_session_cache_limiter();
+ if (php_session_initialize() == FAILURE
+ || php_session_cache_limiter() == -2) {
+ PS(session_status) = php_session_none;
+ if (PS(id)) {
+ zend_string_release(PS(id));
+ PS(id) = NULL;
+ }
+ return FAILURE;
+ }
+ return SUCCESS;
}
/* }}} */
-static void php_session_flush(int write) /* {{{ */
+PHPAPI int php_session_flush(int write) /* {{{ */
{
if (PS(session_status) == php_session_active) {
php_session_save_current_state(write);
PS(session_status) = php_session_none;
+ return SUCCESS;
}
+ return FAILURE;
}
/* }}} */
-static void php_session_abort(void) /* {{{ */
+static int php_session_abort(void) /* {{{ */
{
if (PS(session_status) == php_session_active) {
if (PS(mod_data) || PS(mod_user_implemented)) {
PS(mod)->s_close(&PS(mod_data));
}
PS(session_status) = php_session_none;
+ return SUCCESS;
}
+ return FAILURE;
}
/* }}} */
-static void php_session_reset(void) /* {{{ */
+static int php_session_reset(void) /* {{{ */
{
- if (PS(session_status) == php_session_active) {
- php_session_initialize();
+ if (PS(session_status) == php_session_active
+ && php_session_initialize() == SUCCESS) {
+ return SUCCESS;
}
+ return FAILURE;
}
/* }}} */
@@ -1580,7 +1655,7 @@ PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t
* Userspace exported functions *
******************************** */
-/* {{{ proto void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly]]]])
+/* {{{ proto bool session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly]]]])
Set session cookie parameters */
static PHP_FUNCTION(session_set_cookie_params)
{
@@ -1595,33 +1670,61 @@ static PHP_FUNCTION(session_set_cookie_params)
return;
}
+
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change session cookie parameters when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change session cookie parameters when headers already sent");
+ RETURN_FALSE;
+ }
+
convert_to_string_ex(lifetime);
ini_name = zend_string_init("session.cookie_lifetime", sizeof("session.cookie_lifetime") - 1, 0);
- zend_alter_ini_entry(ini_name, Z_STR_P(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ if (zend_alter_ini_entry(ini_name, Z_STR_P(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
+ zend_string_release(ini_name);
+ RETURN_FALSE;
+ }
zend_string_release(ini_name);
if (path) {
ini_name = zend_string_init("session.cookie_path", sizeof("session.cookie_path") - 1, 0);
- zend_alter_ini_entry(ini_name, path, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ if (zend_alter_ini_entry(ini_name, path, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
+ zend_string_release(ini_name);
+ RETURN_FALSE;
+ }
zend_string_release(ini_name);
}
if (domain) {
ini_name = zend_string_init("session.cookie_domain", sizeof("session.cookie_domain") - 1, 0);
- zend_alter_ini_entry(ini_name, domain, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ if (zend_alter_ini_entry(ini_name, domain, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
+ zend_string_release(ini_name);
+ RETURN_FALSE;
+ }
zend_string_release(ini_name);
}
if (argc > 3) {
ini_name = zend_string_init("session.cookie_secure", sizeof("session.cookie_secure") - 1, 0);
- zend_alter_ini_entry_chars(ini_name, secure ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ if (zend_alter_ini_entry_chars(ini_name, secure ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
+ zend_string_release(ini_name);
+ RETURN_FALSE;
+ }
zend_string_release(ini_name);
}
if (argc > 4) {
ini_name = zend_string_init("session.cookie_httponly", sizeof("session.cookie_httponly") - 1, 0);
- zend_alter_ini_entry_chars(ini_name, httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ if (zend_alter_ini_entry_chars(ini_name, httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
+ zend_string_release(ini_name);
+ RETURN_FALSE;
+ }
zend_string_release(ini_name);
}
+
+ RETURN_TRUE;
}
/* }}} */
@@ -1654,6 +1757,16 @@ static PHP_FUNCTION(session_name)
return;
}
+ if (name && PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change session name when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change session name when headers already sent");
+ RETURN_FALSE;
+ }
+
RETVAL_STRING(PS(session_name));
if (name) {
@@ -1675,6 +1788,16 @@ static PHP_FUNCTION(session_module_name)
return;
}
+ if (name && PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save handler module when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save handler module when headers already sent");
+ RETURN_FALSE;
+ }
+
/* Set return_value to current module name */
if (PS(mod) && PS(mod)->s_name) {
RETVAL_STRING(PS(mod)->s_name);
@@ -1701,7 +1824,7 @@ static PHP_FUNCTION(session_module_name)
}
/* }}} */
-/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc, string create_sid)
+/* {{{ proto bool session_set_save_handler(string open, string close, string read, string write, string destroy, string gc, string create_sid)
Sets user-level functions */
static PHP_FUNCTION(session_set_save_handler)
{
@@ -1710,7 +1833,13 @@ static PHP_FUNCTION(session_set_save_handler)
zend_string *name;
zend_string *ini_name, *ini_val;
- if (PS(session_status) != php_session_none) {
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save handler when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save handler when headers already sent");
RETURN_FALSE;
}
@@ -1807,7 +1936,9 @@ static PHP_FUNCTION(session_set_save_handler)
if (PS(mod) && PS(session_status) != php_session_active && PS(mod) != &ps_mod_user) {
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
+ PS(set_handler) = 1;
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ PS(set_handler) = 0;
zend_string_release(ini_val);
zend_string_release(ini_name);
}
@@ -1840,7 +1971,9 @@ static PHP_FUNCTION(session_set_save_handler)
if (PS(mod) && PS(mod) != &ps_mod_user) {
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
+ PS(set_handler) = 1;
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ PS(set_handler) = 0;
zend_string_release(ini_val);
zend_string_release(ini_name);
}
@@ -1867,6 +2000,16 @@ static PHP_FUNCTION(session_save_path)
return;
}
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save path when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change save path when headers already sent");
+ RETURN_FALSE;
+ }
+
RETVAL_STRING(PS(save_path));
if (name) {
@@ -1893,6 +2036,11 @@ static PHP_FUNCTION(session_id)
return;
}
+ if (name && SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change session id when headers already sent");
+ RETURN_FALSE;
+ }
+
if (PS(id)) {
/* keep compatibility for "\0" characters ???
* see: ext/session/tests/session_id_error3.phpt */
@@ -1931,7 +2079,7 @@ static PHP_FUNCTION(session_regenerate_id)
RETURN_FALSE;
}
- if (SG(headers_sent) && PS(use_cookies)) {
+ if (SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent");
RETURN_FALSE;
}
@@ -2007,13 +2155,15 @@ static PHP_FUNCTION(session_regenerate_id)
if (PS(use_cookies)) {
PS(send_cookie) = 1;
}
- php_session_reset_id();
+ if (php_session_reset_id() == FAILURE) {
+ RETURN_FALSE;
+ }
RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void session_create_id([string prefix])
+/* {{{ proto string session_create_id([string prefix])
Generate new session ID. Intended for user save handlers. */
/* This is not used yet */
static PHP_FUNCTION(session_create_id)
@@ -2078,6 +2228,16 @@ static PHP_FUNCTION(session_cache_limiter)
return;
}
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change cache limiter when session is active");
+ RETURN_FALSE;
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change cache limiter when headers already sent");
+ RETURN_FALSE;
+ }
+
RETVAL_STRING(PS(cache_limiter));
if (limiter) {
@@ -2099,6 +2259,16 @@ static PHP_FUNCTION(session_cache_expire)
return;
}
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot change cache expire when session is active");
+ RETURN_LONG(PS(cache_expire));
+ }
+
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot change cache expire when headers already sent");
+ RETURN_FALSE;
+ }
+
RETVAL_LONG(PS(cache_expire));
if (expires) {
@@ -2135,15 +2305,15 @@ static PHP_FUNCTION(session_decode)
{
zend_string *str = NULL;
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
+ return;
+ }
+
if (PS(session_status) != php_session_active) {
php_error_docref(NULL, E_WARNING, "Session is not active. You cannot decode session data");
RETURN_FALSE;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
- return;
- }
-
if (php_session_decode(str) == FAILURE) {
RETURN_FALSE;
}
@@ -2177,6 +2347,21 @@ static PHP_FUNCTION(session_start)
RETURN_FALSE;
}
+ if (PS(session_status) == php_session_active) {
+ php_error_docref(NULL, E_NOTICE, "A session had already been started - ignoring");
+ RETURN_TRUE;
+ }
+
+ /*
+ * TODO: To prevent unusable session with trans sid, actual output started status is
+ * required. i.e. There shouldn't be any outputs in output buffer, otherwise session
+ * module is unable to rewrite output.
+ */
+ if (SG(headers_sent)) {
+ php_error_docref(NULL, E_WARNING, "Cannot start session when headers already sent");
+ RETURN_FALSE;
+ }
+
/* set options */
if (options) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), num_idx, str_idx, value) {
@@ -2208,6 +2393,12 @@ static PHP_FUNCTION(session_start)
php_session_start();
if (PS(session_status) != php_session_active) {
+ IF_SESSION_VARS() {
+ zval *sess_var = Z_REFVAL(PS(http_session_vars));
+ SEPARATE_ARRAY(sess_var);
+ /* Clean $_SESSION. */
+ zend_hash_clean(Z_ARRVAL_P(sess_var));
+ }
RETURN_FALSE;
}
@@ -2231,10 +2422,14 @@ static PHP_FUNCTION(session_destroy)
}
/* }}} */
-/* {{{ proto void session_unset(void)
+/* {{{ proto bool session_unset(void)
Unset all registered variables */
static PHP_FUNCTION(session_unset)
{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
if (PS(session_status) != php_session_active) {
RETURN_FALSE;
}
@@ -2246,6 +2441,7 @@ static PHP_FUNCTION(session_unset)
/* Clean $_SESSION. */
zend_hash_clean(Z_ARRVAL_P(sess_var));
}
+ RETURN_TRUE;
}
/* }}} */
@@ -2274,27 +2470,51 @@ static PHP_FUNCTION(session_gc)
/* }}} */
-/* {{{ proto void session_write_close(void)
+/* {{{ proto bool session_write_close(void)
Write session data and end session */
static PHP_FUNCTION(session_write_close)
{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ if (PS(session_status) != php_session_active) {
+ RETURN_FALSE;
+ }
php_session_flush(1);
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void session_abort(void)
+/* {{{ proto bool session_abort(void)
Abort session and end session. Session data will not be written */
static PHP_FUNCTION(session_abort)
{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ if (PS(session_status) != php_session_active) {
+ RETURN_FALSE;
+ }
php_session_abort();
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void session_reset(void)
+/* {{{ proto bool session_reset(void)
Reset session data from saved session data */
static PHP_FUNCTION(session_reset)
{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ if (PS(session_status) != php_session_active) {
+ RETURN_FALSE;
+ }
php_session_reset();
+ RETURN_TRUE;
}
/* }}} */
@@ -2607,6 +2827,7 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */
ps_globals->mod_user_implemented = 0;
ps_globals->mod_user_is_open = 0;
ps_globals->session_vars = NULL;
+ ps_globals->set_handler = 0;
for (i = 0; i < PS_NUM_APIS; i++) {
ZVAL_UNDEF(&ps_globals->mod_user_names.names[i]);
}
@@ -2993,6 +3214,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
if (PS(rfc1867_cleanup)) {
php_session_rfc1867_cleanup(progress);
} else {
+ SEPARATE_ARRAY(&progress->data);
add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1);
Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
php_session_rfc1867_update(progress, 1);