Bug #78410 [Opn->Asn]: Cannot "manually" unserialize class that is final and extends an internal one
| From: | nikic@php.net | Date: | Tue, 13 Aug 2019 17:30:35 +0000 |
| Subject: | Bug #78410 [Opn->Asn]: Cannot "manually" unserialize class that is final and extends an internal one | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-222234@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78410&edit=1
ID: 78410
Updated by: nikic@php.net
Reported by: nicolas dot grekas+php at gmail dot com
Summary: Cannot "manually" unserialize class that is final
and extends an internal one
-Status: Open
+Status: Assigned
Type: Bug
Package: *General Issues
PHP Version: 7.4.0beta2
-Assigned To:
+Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
> In that case we should remove the Reflection restriction instead, because that's what this
> is effectively doing, just in a more roundabout way. But that restriction exists for a reason.
Having just looked at the implementation: The Reflection restriction is actually stricter than it
needs to be. It prohibits newInstanceWithoutConstructor for final classes that *inherit* from
internal classes as well, which should not the case. We should only be restricting final, internal
classes.
I don't really understand your original issue, but this is something we can certainly relax...
Previous Comments:
------------------------------------------------------------------------
[2019-08-13 17:27:20] nikic@php.net
I don't really understand what the intent here is ... why is it not possible to provide a
correct O-format string to create the object? It's not going to work with an empty payload, but
then again I don't think it worked with an empty C-payload before either ... right?
> The simplest way I can think of to unlock progress is to allow
> unserialize('O:8:"Foo":0:{}') to work. Doing so *would not call __unserialize*
> but would return an empty object, as it does for classes that don't implement the method.
In that case we should remove the Reflection restriction instead, because that's what this is
effectively doing, just in a more roundabout way. But that restriction exists for a reason.
------------------------------------------------------------------------
[2019-08-13 17:19:32] nicolas dot grekas+php at gmail dot com
Description:
------------
I'm trying to make the VarExporter component of Symfony work on PHP 7.4 and I'm in a
dead-end. What the component provides is an implementation of serialize/unserialize using PHP as the
serialization format. This cannot be implemented anymore in PHP 7.4 with the new
__serialize/__unserialize methods.
The case that breaks is when a userland class is made final *and* extends an internal one.
E.g. final class Foo extends extends \ArrayIterator {...}
Because of these two conditions, ReflectionClass::newInstanceWithoutConstructor is forbidden. In PHP
<=7.3, it is possible to work around the limitation by calling serialize() with a proper payload:
either an empty "O:"-one when the class doesn't implement Serializable, or a
"C:"-one when it does.
To implement the semantics of __unserialize, I cannot use "C:"-format.
And PHP 7.4 complains if I unserialize('O:8:"Foo":0:{}'). That's my
dead-end: I cannot create such an instance to call __unserialize in userland.
The simplest way I can think of to unlock progress is to allow
unserialize('O:8:"Foo":0:{}') to work. Doing so *would not call __unserialize*
but would return an empty object, as it does for classes that don't implement the method.
Thank you for your help, this is a critical blocker for us.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78410&edit=1