Arquivos
hhvm/hphp/runtime/ext/ext_closure.cpp
T
Mike Magruder 8283969d81 Don't serialize cppext instances unless they opt-in, and pass the class name for the debugger
Most CPP extension classes don’t think about serialization, and some require more initialization than the default contractor provides. The result is that on deserialization we end up with a partially initialized object, and undefined behavior after that.

Modified the serializer to emit __PHP_Unserializable_Class instead, and just the class name for the debugger case. Modified the deserializer to create a __PHP_Unserializable_Class, too, if we are given a string with a CPP extension instance in it, so we're safe on both sides. I do not raise a warning; the results are pretty clear, I think, and it's also unlikely that most such warnings could (or should) be corrected. Finally, I also removed the odd behavior of emitting "dummy" classes for Closure and Continuation. I found no use of these in any source tree. Closure had no implementation at all, and Continuation had an implementation that simply raised a fatal on any method call. Thus we can safely assume that even if someone was serializing one of these types, they were receiving an object that was useless to them, or would fatal. So I believe this transformation is safe.
2013-07-23 11:44:16 -07:00

90 linhas
3.3 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/ext/ext_closure.h"
#include "hphp/runtime/base/builtin_functions.h"
#include "hphp/runtime/vm/jit/translator-inline.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
c_Closure::c_Closure(Class* cb) : ExtObjectData(cb),
m_thisOrClass(nullptr), m_func(nullptr) {}
c_Closure::~c_Closure() {
// same as ar->hasThis()
if (m_thisOrClass && !(intptr_t(m_thisOrClass) & 3LL)) {
m_thisOrClass->decRefCount();
}
}
void c_Closure::t___construct() {
raise_error("Can't create a Closure directly");
}
/**
* sp points to the last use variable on the stack.
* returns the closure so that translator-x64 can just return "rax".
*/
c_Closure* c_Closure::init(int numArgs, ActRec* ar, TypedValue* sp) {
static StringData* invokeName = StringData::GetStaticString("__invoke");
Func* invokeFunc = getVMClass()->lookupMethod(invokeName);
if (invokeFunc->attrs() & AttrStatic) {
// Only set the class for static closures
m_thisOrClass = (ObjectData*)(intptr_t(ar->m_func->cls()) | 1LL);
} else {
// I don't care if it is a $this or a late bound class because we will just
// put it back in the same place on an ActRec.
m_thisOrClass = ar->m_this;
if (ar->hasThis()) {
ar->getThis()->incRefCount();
}
}
// Change my __invoke's m_cls to be the same as my creator's
Class* scope = ar->m_func->cls();
m_func = invokeFunc->cloneAndSetClass(scope);
// copy the props to instance variables
assert(m_cls->numDeclProperties() == numArgs);
TypedValue* beforeCurUseVar = sp + numArgs;
TypedValue* curProperty = propVec();
for (int i = 0; i < numArgs; i++) {
// teleport the references in here so we don't incref
*curProperty++ = *--beforeCurUseVar;
}
return this;
}
c_Closure* c_Closure::clone() {
auto closure = static_cast<c_Closure*>(ObjectData::clone());
closure->m_VMStatics = m_VMStatics;
closure->m_thisOrClass = m_thisOrClass;
closure->m_func = m_func;
return closure;
}
HphpArray* c_Closure::getStaticLocals() {
if (m_VMStatics.get() == NULL) {
m_VMStatics = ArrayData::Make(1);
}
return m_VMStatics.get();
}
///////////////////////////////////////////////////////////////////////////////
}