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) /* {{{ */
{
int res;
if (!PS(serializer)) {
php_error_docref(NULL, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
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_track_init();
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) {
session_decode($data);
return null;
}
}
@ -33,20 +34,18 @@ for ($i = 0; $i < 5; $i++) {
var_dump($data);
var_dump($_SESSION);
?>
--EXPECTF--
--EXPECT--
array(2) {
[0]=>
object(obj)#%d (1) {
["data"]=>
NULL
}
[1]=>
object(obj)#%d (1) {
["data"]=>
NULL
}
}
object(obj)#1 (1) {
["data"]=>
NULL
}
[1]=>
object(obj)#2 (1) {
["data"]=>
NULL
}
}
array(0) {
}