Initialize all fields of Static{Result|Exception}WaitHandle
We force users to use the create() methods of StaticResultWaitHandle and StaticExceptionWaitHandle, which properly set m_resultOrException. However, deserialization will use the normal constructor which was failing to initialize the field. The destructor, then, would operate on random data. This broke hphpd when a stack trace had one of these objects on it somewhere. The 'where' command would succeed, but the next command (which deletes the stack trace), would segfault in the wait handle's destructor. I think it's fair to not serialize this member. It's not exposed thru PHP except via joining with the wait handle, and I think an argument can be made that it's just plain wrong to join with a deserialized copy of a wait handle. So I've just initialized it to a reasonable default.
Esse commit está contido em:
@@ -31,7 +31,7 @@ c_StaticExceptionWaitHandle::c_StaticExceptionWaitHandle(Class* cb)
|
||||
}
|
||||
|
||||
c_StaticExceptionWaitHandle::~c_StaticExceptionWaitHandle() {
|
||||
tvDecRefObj(&m_resultOrException);
|
||||
tvRefcountedDecRefCell(&m_resultOrException);
|
||||
}
|
||||
|
||||
void c_StaticExceptionWaitHandle::t___construct() {
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
c_WaitHandle::c_WaitHandle(Class* cb)
|
||||
: ExtObjectData(cb) {
|
||||
: ExtObjectData(cb), m_resultOrException(make_tv<KindOfNull>()) {
|
||||
}
|
||||
|
||||
c_WaitHandle::~c_WaitHandle() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?hh
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
function main() {
|
||||
// Make new wait handles with valid values.
|
||||
$srwh = StaticResultWaitHandle::create(42);
|
||||
$r = $srwh->join();
|
||||
var_dump($r); // Shows 42 correctly.
|
||||
|
||||
$sewh = StaticExceptionWaitHandle::create(new Exception("Hi!"));
|
||||
try {
|
||||
$r = $sewh->join();
|
||||
} catch (Exception $e) {
|
||||
var_dump($e->getMessage()); // Shows "Hi!" correctly.
|
||||
}
|
||||
|
||||
// Serialize the handles and let them go.
|
||||
$s1 = serialize($srwh);
|
||||
$s2 = serialize($sewh);
|
||||
var_dump($s1);
|
||||
var_dump($s2);
|
||||
$srwh = null;
|
||||
$erwh = null;
|
||||
|
||||
// Deserialize the handles in the reverse order, so they lay over
|
||||
// each other's memory. We want to confirm that all fields are
|
||||
// initialized correctly and that the destructor does not segfault.
|
||||
$sewh = unserialize($s2);
|
||||
$sewh = null; // Let it go
|
||||
$srwh = unserialize($s1);
|
||||
$srwh = null; // Let it go
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,4 @@
|
||||
int(42)
|
||||
string(3) "Hi!"
|
||||
string(34) "O:22:"StaticResultWaitHandle":0:{}"
|
||||
string(37) "O:25:"StaticExceptionWaitHandle":0:{}"
|
||||
Referência em uma Nova Issue
Bloquear um usuário