-
Notifications
You must be signed in to change notification settings - Fork 3k
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
HHVM incorrectly returns a "valid" (but not initialized) object from a broken serialization string #6032
Comments
Unfortunately, this does not work because of facebook/hhvm#6032
The way this API currently works requires that the native classes declare C++ sleep and wakeup functions. To do this declare functions named sleep and wakeup on the native-data struct for your class. The sleep function takes no arguments and returns the Variant to be serialized, the wakeup function takes a context argument (Variant) and an ObjectData argument (the object being unserialized), and returns void. You should be able to throw the exceptions directly fromt these functions. |
I've tested this now, and implemented it as follows:
This works fine, I get the exception, however, I also get an "improper" object. Code:
PHP does:
HHVM does:
An exception thrown in a constructor (or wakeup), should not result in a "valid" object, which subsequently crashes when using it, as it has not been setup correctly (hence the throwing of an exception): Code:
PHP:
HHVM:
So how do I make it not return a "valid" object, but instead return "false", like PHP does? |
Looking at the serialize/unserialize code I think what you actually want to do is throw an throw Exception("Unserialization of MongoDB\\Driver\\Manager is not allowed"); |
Okay - there are actually two things at play here:
Code:
PHP throws a warning, and returns "NULL" while deserialization of a broken string:
HHVM doesn't throw a warning, and returns an improperly initialised object:
Making use of this improperly initialized object makes things crash - because the constructor would have filled in some internal structures. This is what needs fixing in HHVM. It should ideally throw a warning, but certainly not return a pseudo-valid object. |
So, the way you're doing things for serialize sounds right. What I don't follow is how throwing an hhvm/hphp/runtime/base/builtin-functions.cpp Lines 745 to 753 in 6cff345
|
I used GDB in anger this morning, and I found the following while going through hhvm/hphp/runtime/base/type-variant.cpp Lines 865 to 976 in 6cff345
The code never bothers calling the
However, it does call the HHVM_METHOD function hhvm/hphp/runtime/base/type-variant.cpp Lines 969 to 973 in 6cff345
In the end, I have made it work with this:
So there seem the be the following issues:
|
Can I please have a comment on both points? |
The native wakeup function is only called if the serialized string contains a native-data key ("\0native"). On the second point, HHVM raises an notice and returns false when it catches an exception in unserialize, see the link below. hhvm/hphp/runtime/base/builtin-functions.cpp Lines 755 to 759 in bbff70c
|
| The native wakeup function is only called if the serialized string contains a native-data key ("\0native"). What's the point with that? How do I define a wake-up handler in my class then? Do I really have to use
Even though there is a native method, which just doesn't happen to be called? I can't just add a "\0native" into my unserialized data to trigger the wakeup function on the ObjectData... | On the second point, HHVM raises an notice and returns false when it catches an exception in unserialize, see the link below. Yes, it does. However, what it does not do is detect that the string: 'O:22:"MongoDB\Driver\Manager":0:{}' is not a valid serializable representation. In PHP, it triggers the code: https://github.com/php/php-src/blob/master/ext/standard/var_unserializer.re#L450-L468 |
I am working on a driver for MongoDB, mimicking the same API as one for PHP. In our extension, we have a couple of built-in classes, that we don't want to serialize (or inherit from). We can signal that by setting class handlers for serialize and unserialize:
zend_class_serialize_deny
andzend_class_unserialize_deny
both throw an exception in the case such an object are attempted to be serialized or deserialized:I was attempting to do imitate the same behaviour with HHVM, by creating a trait:
But the methods are never called, and HHVM insists on just throwing a warning:
Warning: Attempted to serialize unserializable builtin class MongoDB\Driver\Manager in
This happens because of https://github.com/facebook/hhvm/blob/HHVM-3.9/hphp/runtime/base/object-data.cpp#L855
(In master, it is now at https://github.com/facebook/hhvm/blob/master/hphp/runtime/base/variable-serializer.cpp#L1517)
It will always do this, unless
isCppSerializable
is part of the class info flags, which I don't seem to be able to set myself.So the question is really:
The text was updated successfully, but these errors were encountered: