Bug #79031 [Ver]: Session unserialization problem

From: Date: Mon, 30 Dec 2019 10:21:41 +0000
Subject: Bug #79031 [Ver]: Session unserialization problem
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-224609@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
 Updated by:         nikic@php.net
 Reported by:        syberon at gmail dot com
 Summary:            Session unserialization problem
 Status:             Verified
 Type:               Bug
 Package:            Session related
 Operating System:   Windows 10 1909
 PHP Version:        7.4.1
 Assigned To:        nikic
 Block user comment: N
 Private report:     N

 New Comment:

Looks like this is a general bug in how serialization locking is handled. Here's a case without
using sessions: https://3v4l.org/cZqVf The inner objects should
be the same, but they're different.


Previous Comments:
------------------------------------------------------------------------
[2019-12-27 16:53:17] cmb@php.net

This regression has apparently been introduced with commit
b8ef7c3[1].  Nikita, could you have a look please?

[1] <http://git.php.net/?p=php-src.git;a=commit;h=b8ef7c35abd31666d9fb317db4b09a9eef0ede6c>

------------------------------------------------------------------------
[2019-12-27 09:24:53] aleksey at xerkus dot pro

https://3v4l.org/NPt2R This slightly modified example from
comment above showcases the issue
https://3v4l.org/HeLT4 This example uses
php_serialize session serializer and exhibits exactly the same behavior.

------------------------------------------------------------------------
[2019-12-27 08:20:29] syberon at gmail dot com

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.

------------------------------------------------------------------------
[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


Thread (7 messages)

« previous php.bugs (#224609) next »