From b8ef7c35abd31666d9fb317db4b09a9eef0ede6c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 25 Sep 2019 11:02:23 +0200 Subject: [PATCH] Increase serialize_lock while decoding session Avoid leaking state between Serializable::unserialize() and session_decode(). --- ext/session/session.c | 9 ++++++++- ext/standard/tests/serialize/bug70219_1.phpt | 11 +++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ext/session/session.c b/ext/session/session.c index 671968e8da..01c2d4b85a 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -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"); diff --git a/ext/standard/tests/serialize/bug70219_1.phpt b/ext/standard/tests/serialize/bug70219_1.phpt index 6bbc593b34..6492a9a21e 100644 --- a/ext/standard/tests/serialize/bug70219_1.phpt +++ b/ext/standard/tests/serialize/bug70219_1.phpt @@ -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) { + object(obj)#1 (1) { ["data"]=> NULL } [1]=> - object(obj)#%d (1) { + object(obj)#2 (1) { ["data"]=> NULL } } -object(obj)#1 (1) { - ["data"]=> - NULL +array(0) { } -- 2.40.0