diff --git a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp index 4841c6346..c5e3b304f 100644 --- a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp @@ -1771,6 +1771,11 @@ void HhbcTranslator::emitFPushObjMethodD(int32_t numParams, nullptr); auto const actRec = spillStack(); auto const objCls = gen(LdObjClass, obj); + + // This is special. We need to move the stackpointer incase LdObjMethod + // calls a destructor. Otherwise it would clobber the ActRec we just pushed. + emitMarker(); + gen(LdObjMethod, objCls, cns(methodName), diff --git a/hphp/runtime/vm/translator/targetcache.cpp b/hphp/runtime/vm/translator/targetcache.cpp index 59a2e904c..c4b78b5ca 100644 --- a/hphp/runtime/vm/translator/targetcache.cpp +++ b/hphp/runtime/vm/translator/targetcache.cpp @@ -539,6 +539,14 @@ void methodCacheSlowPath(MethodCache::Pair* mce, ObjectData* arThis = ar->getThis(); shouldBeObj->m_type = KindOfObject; shouldBeObj->m_data.pobj = arThis; + + // There used to be a half-built ActRec on the stack that we need the + // unwinder to ignore. We overwrote 1/3 of it with the code above, but + // because of the emitMarker() in LdObjMethod we need the other two slots + // to not have any TypedValues. + tvWriteNull(shouldBeObj-1); + tvWriteNull(shouldBeObj-2); + throw; } } diff --git a/hphp/test/quick/destruct_segfault.php b/hphp/test/quick/destruct_segfault.php new file mode 100644 index 000000000..8e1e799b5 --- /dev/null +++ b/hphp/test/quick/destruct_segfault.php @@ -0,0 +1,19 @@ +b(); +} +main(); diff --git a/hphp/test/quick/destruct_segfault.php.expect b/hphp/test/quick/destruct_segfault.php.expect new file mode 100644 index 000000000..d115e2bbe --- /dev/null +++ b/hphp/test/quick/destruct_segfault.php.expect @@ -0,0 +1 @@ +no segfault \ No newline at end of file diff --git a/hphp/test/slow/redeclared_classes/1474.php b/hphp/test/slow/redeclared_classes/1474.php index e4caef5a1..cbd4aceb5 100644 --- a/hphp/test/slow/redeclared_classes/1474.php +++ b/hphp/test/slow/redeclared_classes/1474.php @@ -1,3 +1,24 @@ bar(); $x = new V; $x->bar();}test(); \ No newline at end of file +function nop($en,$es){}; +set_error_handler('nop'); +class X { + function bar() { + var_dump($this); + } +} +if (1) { + class U { } +} else { + class U extends X { } +} + +class V extends U {} + +function test() { + $x = new X; + $x->bar(); + $x = new V; + $x->bar(); +} +test();