You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$foo may contain data that is either serialized or unserialized.
If it is serialized, I need to unserialize to ensure $foo is now in a consistent, unserialized state.
Best I can tell there is no official way to detect if something can be unserialized. So the way I had implemented was in a seemingly-innocent try/catch block:
However this now causes \Opis\Closure to enter essentially a broken state if the try block fails. As soon as that occurs, the locks depth used in \Opis\Closure\SerializableContext::enterContext will now never reach zero, causing all future serializations to happen in the same context. There is no way to forcibly reset the context state either.
This creates some extremely random bugs - in my situation certain tests late in the test suite fail because when attempting to serialize an object instance using \Opis\Closure\serialize, \Opis\Closure\SerializableClosure::wrapClosures updates the instance by reference to become simply boolean true. This happens because we are attempting to serialize inside the context of a previous serialization ... but only if specific other tests earlier in the suite were run first. The tests are bleeding into each other due to \Opis\Closure's essentially global state.
In a wider use case, its not unforeseeable that someone would try unserializing in a much wider try/catch block than my example above. If it falls over and their code execution continues, it is going to produce some very bizarre & hard-to-track-down bugs.
So best I can tell I'm stuck with the current implementation. For now I've just created a class that extends \Opis\Closure\SerializableClosure and provides a clean method:
/** * Restore Opis\Closure to a clean state, read for the next call to * serialize/unserialize * * @return void */publicstaticfunctionclean()
{
static::$context = null;
}
Perhaps unserialize itself should wrap the unserialization in a try/finally so it can ensure the context is exited before passing any exceptions on
eg in functions.php
(BTW, I had to check for myself that finally runs here before passing that exception on in the absence of a catch : I can confirm it does behave as expected and run the exitContext in that case before then passing that exception on as-per normal. For some reason in all my years of PHP of never really come across that requirement before and the docs are vague on the subject
)
I have the following use case:
$foo
may contain data that is either serialized or unserialized.$foo
is now in a consistent, unserialized state.Best I can tell there is no official way to detect if something can be unserialized. So the way I had implemented was in a seemingly-innocent try/catch block:
Now
$bar
is always unserialized.However this now causes
\Opis\Closure
to enter essentially a broken state if thetry
block fails. As soon as that occurs, thelocks
depth used in\Opis\Closure\SerializableContext::enterContext
will now never reach zero, causing all future serializations to happen in the same context. There is no way to forcibly reset the context state either.This creates some extremely random bugs - in my situation certain tests late in the test suite fail because when attempting to serialize an object instance using
\Opis\Closure\serialize
,\Opis\Closure\SerializableClosure::wrapClosures
updates the instance by reference to become simply booleantrue
. This happens because we are attempting to serialize inside the context of a previous serialization ... but only if specific other tests earlier in the suite were run first. The tests are bleeding into each other due to\Opis\Closure
's essentially global state.In a wider use case, its not unforeseeable that someone would try unserializing in a much wider try/catch block than my example above. If it falls over and their code execution continues, it is going to produce some very bizarre & hard-to-track-down bugs.
So best I can tell I'm stuck with the current implementation. For now I've just created a class that extends
\Opis\Closure\SerializableClosure
and provides aclean
method:Now I can clean up as required:
Now it cleans up after itself & allows future serialization.
I'm mainly just reporting this in case its of use to you guys - but a couple of suggestions for your consideration:
clean
method, or some other way to restore to a clean state / forcibly exit the current context as I've done aboveThe text was updated successfully, but these errors were encountered: