Skip to content

Commit 05d53de

Browse files
committed
Fixed bug #71972 (Cyclic references causing session_start(): Failed to decode session object)
1 parent edb569b commit 05d53de

File tree

3 files changed

+73
-21
lines changed

3 files changed

+73
-21
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ PHP NEWS
1414
. Fixed bug #71062 (pg_convert() doesn't accept ISO 8601 for datatype
1515
timestamp). (denver at timothy dot io)
1616

17+
- Session:
18+
. Fixed bug #71972 (Cyclic references causing session_start(): Failed to
19+
decode session object). (Laruence)
20+
1721
- SQLite3:
1822
. Fixed bug #68849 (bindValue is not using the right data type). (Anatol)
1923

ext/session/session.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ static void php_session_gc(void) /* {{{ */
498498
}
499499
} /* }}} */
500500

501-
502501
static void php_session_initialize(void) /* {{{ */
503502
{
504503
zend_string *val = NULL;
@@ -613,6 +612,22 @@ static void php_session_save_current_state(int write) /* {{{ */
613612
}
614613
/* }}} */
615614

615+
static void php_session_normalize_vars() /* {{{ */
616+
{
617+
PS_ENCODE_VARS;
618+
619+
IF_SESSION_VARS() {
620+
PS_ENCODE_LOOP(
621+
if (Z_TYPE_P(struc) == IS_PTR) {
622+
zval *zv = (zval *)Z_PTR_P(struc);
623+
ZVAL_COPY_VALUE(struc, zv);
624+
ZVAL_UNDEF(zv);
625+
}
626+
);
627+
}
628+
}
629+
/* }}} */
630+
616631
/* *************************
617632
* INI Settings/Handlers *
618633
************************* */
@@ -944,7 +959,6 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
944959
{
945960
const char *p;
946961
const char *endptr = val + vallen;
947-
zval current;
948962
int has_value;
949963
int namelen;
950964
zend_string *name;
@@ -967,28 +981,32 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
967981
p += namelen + 1;
968982

969983
if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
970-
if ((Z_TYPE_P(tmp) == IS_ARRAY && Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
984+
if ((Z_TYPE_P(tmp) == IS_ARRAY &&
985+
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
971986
zend_string_release(name);
972987
continue;
973988
}
974989
}
975990

976991
if (has_value) {
977-
ZVAL_UNDEF(&current);
978-
if (php_var_unserialize(&current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
979-
zval *zv = php_set_session_var(name, &current, &var_hash );
980-
var_replace(&var_hash, &current, zv);
992+
zval *current, rv;
993+
current = var_tmp_var(&var_hash);
994+
if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) {
995+
ZVAL_PTR(&rv, current);
996+
php_set_session_var(name, &rv, &var_hash );
981997
} else {
982-
zval_ptr_dtor(&current);
983998
zend_string_release(name);
999+
php_session_normalize_vars();
9841000
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
9851001
return FAILURE;
9861002
}
1003+
} else {
1004+
PS_ADD_VARL(name);
9871005
}
988-
PS_ADD_VARL(name);
9891006
zend_string_release(name);
9901007
}
9911008

1009+
php_session_normalize_vars();
9921010
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
9931011

9941012
return SUCCESS;
@@ -1033,10 +1051,9 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
10331051
{
10341052
const char *p, *q;
10351053
const char *endptr = val + vallen;
1036-
zval current;
1037-
int has_value;
10381054
ptrdiff_t namelen;
10391055
zend_string *name;
1056+
int has_value, retval = SUCCESS;
10401057
php_unserialize_data_t var_hash;
10411058

10421059
PHP_VAR_UNSERIALIZE_INIT(var_hash);
@@ -1061,34 +1078,37 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
10611078
q++;
10621079

10631080
if ((tmp = zend_hash_find(&EG(symbol_table), name))) {
1064-
if ((Z_TYPE_P(tmp) == IS_ARRAY && Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
1081+
if ((Z_TYPE_P(tmp) == IS_ARRAY &&
1082+
Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) {
10651083
goto skip;
10661084
}
10671085
}
10681086

10691087
if (has_value) {
1070-
ZVAL_UNDEF(&current);
1071-
if (php_var_unserialize(&current, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash)) {
1072-
zval *zv = php_set_session_var(name, &current, &var_hash);
1073-
var_replace(&var_hash, &current, zv);
1088+
zval *current, rv;
1089+
current = var_tmp_var(&var_hash);
1090+
if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) {
1091+
ZVAL_PTR(&rv, current);
1092+
php_set_session_var(name, &rv, &var_hash);
10741093
} else {
1075-
zval_ptr_dtor(&current);
1076-
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
10771094
zend_string_release(name);
1078-
return FAILURE;
1095+
retval = FAILURE;
1096+
goto break_outer_loop;
10791097
}
1098+
} else {
1099+
PS_ADD_VARL(name);
10801100
}
1081-
PS_ADD_VARL(name);
10821101
skip:
10831102
zend_string_release(name);
10841103

10851104
p = q;
10861105
}
10871106
break_outer_loop:
1107+
php_session_normalize_vars();
10881108

10891109
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
10901110

1091-
return SUCCESS;
1111+
return retval;
10921112
}
10931113
/* }}} */
10941114

ext/session/tests/bug71972.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Bug #71972 (Cyclic references causing session_start(): Failed to decode session object)
3+
--SKIPIF--
4+
<?php include('skipif.inc'); ?>
5+
--INI--
6+
session.save_handler=files
7+
--FILE--
8+
<?php
9+
ob_start();
10+
session_start();
11+
12+
$_SESSION['boogie'] = 1;
13+
14+
$_SESSION['obj1'] = new stdClass();
15+
for ( $x=2; $x < 20; $x++) {
16+
cyclic_ref($x);
17+
}
18+
19+
function cyclic_ref($num) {
20+
$_SESSION['obj'.$num] = new stdClass();
21+
$_SESSION['obj'.$num]->test = new stdClass();//NOTE: No bug if try commenting out this too.
22+
$_SESSION['obj'.$num]->obj1 = $_SESSION['obj1'];
23+
}
24+
25+
var_dump(session_decode(session_encode()) == $_SESSION);
26+
?>
27+
--EXPECT--
28+
bool(true)

0 commit comments

Comments
 (0)