]> granicus.if.org Git - php/commitdiff
Fix #70013: Reference to $_SESSION is lost after a call to session_regenerate_id()
authorYasuo Ohgaki <yohgaki@php.net>
Sun, 6 Sep 2015 08:14:34 +0000 (17:14 +0900)
committerYasuo Ohgaki <yohgaki@php.net>
Sun, 6 Sep 2015 18:57:03 +0000 (03:57 +0900)
ext/session/session.c
ext/session/tests/bug67694.phpt
ext/session/tests/bug70013.phpt [new file with mode: 0644]

index 46b817be2844dab50bdb1f6ac2c1af892e3b46c6..8c604631aa0c82fa97240736967cf6d76a7bb63b 100644 (file)
@@ -2019,7 +2019,7 @@ static PHP_FUNCTION(session_id)
 static PHP_FUNCTION(session_regenerate_id)
 {
        zend_bool del_ses = 0;
-       zend_string *data = NULL;
+       zend_string *data;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &del_ses) == FAILURE) {
                return;
@@ -2035,25 +2035,70 @@ static PHP_FUNCTION(session_regenerate_id)
                RETURN_FALSE;
        }
 
-       /* Keep current session data */
-       data = php_session_encode();
-
-       if (del_ses && PS(mod)->s_destroy(&PS(mod_data), PS(id)) == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "Session object destruction failed");
+       /* Process old session data */
+       if (del_ses) {
+               if (PS(mod)->s_destroy(&PS(mod_data), PS(id)) == FAILURE) {
+                       PS(mod)->s_close(&PS(mod_data));
+                       PS(session_status) = php_session_none;
+                       php_error_docref(NULL, E_WARNING, "Session object destruction failed.  ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+                       RETURN_FALSE;
+               }
+       } else {
+               int ret;
+               data = php_session_encode();
+               if (data) {
+                       ret = PS(mod)->s_write(&PS(mod_data), PS(id), data, PS(gc_maxlifetime));
+                       zend_string_release(data);
+               } else {
+                       ret = PS(mod)->s_write(&PS(mod_data), PS(id), ZSTR_EMPTY_ALLOC(), PS(gc_maxlifetime));
+               }
+               PS(mod)->s_close(&PS(mod_data));
+               if (ret == FAILURE) {
+                       PS(session_status) = php_session_none;
+                       php_error_docref(NULL, E_WARNING, "Session write failed. ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+                       RETURN_FALSE;
+               }
        }
-       php_rshutdown_session_globals();
-       php_rinit_session_globals();
 
-       php_session_initialize();
-       /* Restore session data */
-       if (data) {
-               if (PS(session_vars)) {
-                       zend_string_release(PS(session_vars));
-                       PS(session_vars) = NULL;
+       /* New session data */
+       if (PS(session_vars)) {
+               zend_string_release(PS(session_vars));
+               PS(session_vars) = NULL;
+       }
+       zend_string_release(PS(id));
+       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 session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+               RETURN_FALSE;
+       }
+       if (PS(use_strict_mode) && PS(mod)->s_validate_sid &&
+               PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == FAILURE) {
+               zend_string_release(PS(id));
+               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 session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+                       RETURN_FALSE;
                }
-               php_session_decode(data);
+       }
+       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 session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+               RETURN_FALSE;
+       }
+       /* 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(session_status) = php_session_none;
+               php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
+               RETURN_FALSE;
+       }
+       if (data) {
                zend_string_release(data);
        }
+
+       php_session_reset_id();
+
        RETURN_TRUE;
 }
 /* }}} */
index bf7089f2c2364648a73ce3d2fec134f2f4950bfb..a82a9fcbaf37c4d8225fcc932f9abf6e485675d4 100644 (file)
@@ -11,7 +11,7 @@ date.timezone = UTC
 <?php include('skipif.inc'); ?>
 --FILE--
 <?php
-
+ob_start();
 $data = date('r');
 
 session_start();
diff --git a/ext/session/tests/bug70013.phpt b/ext/session/tests/bug70013.phpt
new file mode 100644 (file)
index 0000000..739e562
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Bug #70013 (Reference to $_SESSION is lost after a call to session_regenerate_id())
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--INI--
+session.save_handler=files
+--FILE--
+<?php
+ob_start();
+session_start();
+
+$session = &$_SESSION;
+
+$session['test'] = 1;
+session_regenerate_id(false);
+$session['test'] = 2;
+
+var_dump($session['test'] === $_SESSION['test']);
+
+$session['test'] = 3;
+session_regenerate_id(true);
+$session['test'] = 4;
+
+var_dump($session['test'] === $_SESSION['test']);
+?>
+--EXPECT--
+bool(true)
+bool(true)