Increase serialize_lock while decoding session

Avoid leaking state between Serializable::unserialize() and
session_decode().
This commit is contained in:
Nikita Popov 2019-09-25 11:02:23 +02:00
parent b100d51ba2
commit b8ef7c35ab
2 changed files with 13 additions and 7 deletions

View file

@ -244,11 +244,18 @@ static zend_string *php_session_encode(void) /* {{{ */
static int php_session_decode(zend_string *data) /* {{{ */ static int php_session_decode(zend_string *data) /* {{{ */
{ {
int res;
if (!PS(serializer)) { if (!PS(serializer)) {
php_error_docref(NULL, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object"); php_error_docref(NULL, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
return FAILURE; return FAILURE;
} }
if (PS(serializer)->decode(ZSTR_VAL(data), ZSTR_LEN(data)) == FAILURE) { /* Make sure that any uses of unserialize() during session decoding do not share
* state with any unserialize() that is already in progress (e.g. because we are
* currently inside Serializable::unserialize(). */
BG(serialize_lock)++;
res = PS(serializer)->decode(ZSTR_VAL(data), ZSTR_LEN(data));
BG(serialize_lock)--;
if (res == FAILURE) {
php_session_destroy(); php_session_destroy();
php_session_track_init(); php_session_track_init();
php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed"); php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed");

View file

@ -18,6 +18,7 @@ class obj implements Serializable {
} }
function unserialize($data) { function unserialize($data) {
session_decode($data); session_decode($data);
return null;
} }
} }
@ -33,20 +34,18 @@ for ($i = 0; $i < 5; $i++) {
var_dump($data); var_dump($data);
var_dump($_SESSION); var_dump($_SESSION);
?> ?>
--EXPECTF-- --EXPECT--
array(2) { array(2) {
[0]=> [0]=>
object(obj)#%d (1) {
["data"]=>
NULL
}
[1]=>
object(obj)#%d (1) {
["data"]=>
NULL
}
}
object(obj)#1 (1) { object(obj)#1 (1) {
["data"]=> ["data"]=>
NULL NULL
} }
[1]=>
object(obj)#2 (1) {
["data"]=>
NULL
}
}
array(0) {
}