Search code examples
phpserializationsplsplobjectstorage

UnexpectedValueException in session_start() php failing SPLObjectStorage serialization


Why UnexpectedValueException is thrown in session_start()?

I have object which has property of SPLObjectstorage. That object is assigned to session like

$_SESSION['foo'] = $barObject;

I suspect that internal session serializing facing problem to decode it. I store the session in database and it looks like it is serializing the objectStorage but can not decode it.

Sample session data

self|O:4:"User":8:{s:5:"�*�id";N;s:7:"�*�nick";N;s:13:"�*�reputation";i:1;s:11:"�*�password";N;s:8:"�*�email";N;s:7:"�*�crud";O:10:"CRUDobject":2:{s:13:"�*�fieldCache";a:0:{}s:13:"�*�dependency";r:1;}s:7:"�*�auth";N;s:11:"�*�roleList";C:11:"RoleStorage":23:{x:i:1;N;,r:13;;m:a:0:{}}}

Rolestorage is extends of SPLObjectstorage session_decode() on above string also returns false any ideas?

removing the roleList attribute makes it serialize properly.

If I separately do

$sr = serialize($roles); // $roles is RoleStorage object
var_dump($sr);
var_dump(unserialize($sr));

It prints string 'C:11:"RoleStorage":22:{x:i:1;N;,r:3;;m:a:0:{}}' (length=46) and then fails with same message while unserializing. I have no clue why this is happening.

Note: while attaching object to RoleStorage I used the object itself as data. Means it is stored as reference. I don't know how (if) does serialize() handles internally this.


Solution

  • I have no clue why this is happening

    In your PHP version and with your concrete script it is not possible to serialize an object based on SPLObjectStorage unless you take care of the serialization your own. If you see this part of your serialized string:

    C:11:"RoleStorage":23:{x:i:1;N;,r:13;;m:a:0:{}}
    

    This represents the RoleStorage object. The big C at the beginning stands for:

    C - Object implementing serializeable Interface

    So the object itself is responsible here about the serialization and unserialization. You can normally expect this works, however not all software is without bugs.

    In your case it looks like PHP made a mistake. The internal format here is:

    x:i:1;N;,r:13;;m:a:0:{} 
          ^^^^^^^
    

    And the problem is at the highlighted position, this requires a serialized object, not NULL. And it's not comma-terminated with a reference (r:13 here), but with null (N) to be working.

    So looks like a hick-up triggered by referencing some earlier object (take care that this referencing is not the same as references / variable aliases in userland PHP).

    So how to go on?

    It's time you start to isolate your problem and create a self-contained, reproduceable example out of it. This is necessary to further look into the issue as you see it. This is important for two reasons:

    1. If this is a bug in PHP, it should be reported, a regression test written and added to PHP Q&A and then the bug fixed (if not yet fixed).
    2. If you're looking for a workaround, reproducing the original problem is necessary to create a workaround quickly and easily.

    I did run some tests for a work-around, however so far I'm not able to reproduce your issue so I can not really suggest how to work around the issue as I don't have it here.