Skip to content

Fix GH-8996: DOMNode serialization on PHP ^8.1 #12388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Oct 8, 2023

I have a solution to the problem that can work on 8.1.

Implementing a real serialization and unserialization method isn't really feasible for stable branches, and I'm not even sure how they would correctly behave due to the transient nature even on master, but that's a discussion for another time I guess...

PHP 8.1 introduced a seemingly unintentional BC break in ca94d55 by blocking the (un)serialization of DOM objects.
This was done because the serialization never really worked and just resulted in an empty object, which upon unserialization just resulted in an object that you can't use.

Users can however implement their own serialization methods, but the commit made that impossible as the ACC flag gets passed down to the child class. An approach was tried in #10307 with a new ACC flag to selectively allow serialization with subclasses if they implement the right methods. However, that was found to be too ad hoc.

Instead, let's abuse how the __sleep and __wakeup methods work to throw the exception instead. If the child class implements the __serialize / __unserialize method, then the throwing methods won't be called. Similarly, if the child class implements __sleep and __wakeup, then they're overridden and it doesn't matter that they throw.

For the user, this PR has the exact same behaviour for (sub)classes that don't implement the serialization methods: an exception will be thrown. For code that previously implemented subclasses with these methods, this approach will make that code work again. This approach should be both BC preserving and unbreak user's code.

PHP 8.1 introduced a seemingly unintentional BC break in ca94d55 by
blocking the (un)serialization of DOM objects.
This was done because the serialization never really worked and just
resulted in an empty object, which upon unserialization just resulted in
an object that you can't use.

Users can however implement their own serialization methods, but the
commit made that impossible as the ACC flag gets passed down to the
child class. An approach was tried in php#10307 with a new ACC flag to
selectively allow serialization with subclasses if they implement the
right methods. However, that was found to be too ad hoc.

Instead, let's abuse how the __sleep and __wakeup methods work to throw
the exception instead. If the child class implements the __serialize /
__unserialize method, then the throwing methods won't be called.
Similarly, if the child class implements __sleep and __wakeup, then
they're overridden and it doesn't matter that they throw.

For the user, this PR has the exact same behaviour for (sub)classes that
don't implement the serialization methods: an exception will be thrown.
For code that previously implemented subclasses with these methods, this
approach will make that code work again. This approach should be both BC
preserving and unbreak user's code.

For the test:
Co-authored-by: wazelin <contact@sergeimikhailov.com>
@nielsdos nielsdos requested review from kocsismate and Girgias October 8, 2023 22:22
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually kind of genius.

Only thing I would like to see is a test case with a subclass which implements Serializable

@nielsdos
Copy link
Member Author

nielsdos commented Oct 9, 2023

What do you think of the wording of the exception? It may need something extra to indicate how a developer can still use serialization?
E.g. something like "(...) is not allowed, unless (un)serialization methods are implemented in a subclass" ?

@Girgias
Copy link
Member

Girgias commented Oct 9, 2023

What do you think of the wording of the exception? It may need something extra to indicate how a developer can still use serialization? E.g. something like "(...) is not allowed, unless (un)serialization methods are implemented in a subclass" ?

I think the suggestion is good, but I might mention __serialize() directly, as this should be what people use nowadays.

@nielsdos nielsdos closed this in 24e5e4e Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants