Bug #79031 [Opn]: Session unserialization problem
| From: | syberon at gmail dot com | Date: | Fri, 27 Dec 2019 08:20:29 +0000 |
| Subject: | Bug #79031 [Opn]: Session unserialization problem | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-224547@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=79031&edit=1
ID: 79031
User updated by: syberon at gmail dot com
Reported by: syberon at gmail dot com
Summary: Session unserialization problem
Status: Open
Type: Bug
Package: Session related
Operating System: Windows 10 1909
PHP Version: 7.4.1
Block user comment: N
Private report: N
New Comment:
From observable behavior it appears that unserialize implementation when called by session extension
C code does not set context for unserialize, resulting in relative numbered references being wrong
when used in nested unserialize calls.
Previous Comments:
------------------------------------------------------------------------
[2019-12-27 04:12:43] syberon at gmail dot com
I found that this problem is related to PHP 7.4 session unserializing. I made some tests and found
that if some class (Zend\Stdlib\ArrayObject in my case) implements Serializable interface and has
some property (object of stdClass for example) it failed to decode if stored in session.
I made a minimal reproducible example:
<?php
class SerializableClass implements Serializable {
public $sharedProp;
public function __construct($prop)
{
$this->sharedProp = $prop;
}
public function __set($key, $value)
{
$this->$key = $value;
}
public function serialize()
{
return serialize(get_object_vars($this));
}
public function unserialize($data)
{
$ar = unserialize($data);
foreach ($ar as $k => $v) {
$this->__set($k, $v);
}
}
}
// Shared object that acts as property of two another objects stored in session
$testPropertyObj = new stdClass();
$testPropertyObj->name = 'test';
// Two instances of \SerializableClass that shares property
$sessionObject = [
'obj1' => new SerializableClass($testPropertyObj),
'obj2' => new SerializableClass($testPropertyObj),
];
session_start();
$_SESSION = $sessionObject;
On first run it creates array with two instances of object with one shared property and store it in
session.
On second run it tries to start session and fail to parse the second object stored in session
because the it loses reference to property 'name'.
This script runs without any problems on PHP 7.3, and rises the parse errors on PHP 7.4.
------------------------------------------------------------------------
[2019-12-25 09:52:12] syberon at gmail dot com
Description:
------------
Since version 7.4 of PHP the unserialize function can't process object references from
serialized session strings.
For example, i have a few object stored in session with 3 namespaces (i exploded it to readability:
__ZF|a:2:{s:20:"_REQUEST_ACCESS_TIME";d:1577256665.394478;s:6:"_VALID";a:1:{s:25:"Zend\Session\Validator\Id";s:26:"uk2ngahnpc35k4rfsqd97kf9e6";}}
FlashMessenger|C:23:"Zend\Stdlib\ArrayObject":205:{a:4:{s:7:"storage";a:0:{}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";a:4:{i:0;s:7:"storage";i:1;s:4:"flag";i:2;s:13:"iteratorClass";i:3;s:19:"protectedProperties";}}}
MtCms\User\Authentication\Adapter\DatabaseAdapter|C:23:"Zend\Stdlib\ArrayObject":644:{a:4:{s:7:"storage";a:1:{s:7:"storage";a:2:{s:12:"is_satisfied";b:1;s:8:"identity";O:8:"stdClass":13:{s:2:"id";s:1:"1";s:8:"username";s:5:"admin";s:5:"email";s:17:"syberon@gmail.com";s:12:"display_name";s:6:"Andrey";s:7:"picture";s:0:"";s:8:"delivery";s:1:"1";s:4:"city";s:22:"Ð ÑÐ ÑÐ ÐÐ ÑСÐÐ ÑР±РÑСÐСÐÐ Ñ";s:9:"city_code";s:3:"270";s:8:"zip_code";s:6:"630000";s:7:"address";s:16:"Сâ¹Ð ÐР°Сâ¹Ð ÐР°РÐСâ¹";s:5:"phone";s:4:"4234";s:5:"state";s:1:"1";s:10:"persistent";s:1:"1";}}}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";a:4:{i:0;s:7:"storage";i:1;s:4:"flag";i:2;s:13:"iteratorClass";i:3;s:19:"protectedProperties";}}}
Zend_Auth|C:23:"Zend\Stdlib\ArrayObject":224:{a:4:{s:7:"storage";a:1:{s:7:"storage";r:20;}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";a:4:{i:0;s:7:"storage";i:1;s:4:"flag";i:2;s:13:"iteratorClass";i:3;s:19:"protectedProperties";}}}
Second namespace 'MtCms\User\Authentication\Adapter\DatabaseAdapter' has object of class
'Zend\Stdlib\ArrayObject' that has a property with name 'storage' that contains
anothe object.
Third namespace 'Zend_Auth' has the object of class 'Zend\Stdlib\ArrayObject'
too. And this object has the same property 'storage' but it has value r:20 (reference to
object of second namespace)
PHP 7.3 parses this serialized session data without any problems and at result we have a objects
from 2nd and 3rd namespaces with property 'storage' what have identically object contain
in.
But then i upgraded to PHP 7.4 the session_start() function give the error when trying to parse this
session data. It can not recognize 'r:20' reference in object of 3rd namespace.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79031&edit=1