void autoTypecheck(const Unit* unit) { if (RuntimeOption::RepoAuthoritative || !RuntimeOption::AutoTypecheck || tl_doneAutoTypecheck || !unit->isHHFile()) { return; } tl_doneAutoTypecheck = true; vm_call_user_func("\\HH\\Client\\typecheck_and_error", staticEmptyArray()); }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->m_func; if (LIKELY(func->maybeIntercepted() == 0)) return true; // Intercept only original generator / async function calls, not resumption. if (ar->inGenerator()) return true; Variant *h = get_intercept_handler(func->fullNameRef(), &func->maybeIntercepted()); if (!h) return true; JIT::VMRegAnchor _; PC savePc = g_context->m_pc; Variant doneFlag = true; Variant called_on; if (ar->hasThis()) { called_on = Variant(ar->getThis()); } else if (ar->hasClass()) { // For static methods, give handler the name of called class called_on = Variant(const_cast<StringData*>(ar->getClass()->name())); } Variant intArgs = PackedArrayInit(5) .append(ar->m_func->fullNameRef()) .append(called_on) .append(get_frame_args_with_ref(ar)) .append(h->asCArrRef()[1]) .appendRef(doneFlag) .toArray(); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { Offset pcOff; ActRec* outer = g_context->getPrevVMState(ar, &pcOff); frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals()); Stack& stack = g_context->getStack(); stack.top() = (Cell*)(ar + 1); cellDup(*ret.asCell(), *stack.allocTV()); g_context->m_fp = outer; g_context->m_pc = outer ? outer->m_func->unit()->at(pcOff) : nullptr; return false; } g_context->m_fp = ar; g_context->m_pc = savePc; return true; }
void EventHook::DoMemoryThresholdCallback() { clearSurpriseFlag(MemThresholdFlag); if (!g_context->m_memThresholdCallback.isNull()) { VMRegAnchor _; try { vm_call_user_func(g_context->m_memThresholdCallback, empty_array()); } catch (Object& ex) { raise_error("Uncaught exception escaping mem Threshold callback: %s", ex.toString().data()); } } }
bool f_pcntl_signal_dispatch() { int *signaled = s_signal_handlers->signaled; for (int i = 0; i < _NSIG; i++) { if (signaled[i]) { signaled[i] = 0; if (s_signal_handlers->handlers.exists(i)) { vm_call_user_func(s_signal_handlers->handlers[i], make_packed_array(i)); } } } return true; }
void IntervalTimer::RunCallbacks() { for (auto timer : s_timer_pool->timers) { if (timer->m_signaled.load(std::memory_order_relaxed)) { timer->m_signaled.store(false, std::memory_order_relaxed); try { vm_call_user_func(timer->m_callback, init_null()); } catch (Object& ex) { raise_error("Uncaught exception escaping IntervalTimer: %s", ex.toString().data()); } } } }
Variant f_iterator_apply(CVarRef obj, CVarRef func, CArrRef params /* = null_array */) { Object pobj = get_traversable_object_iterator(obj); pobj->o_invoke_few_args(s_rewind, 0); int64_t count = 0; while (same(pobj->o_invoke_few_args(s_valid, 0), true)) { if (!same(vm_call_user_func(func, params), true)) { break; } ++count; pobj->o_invoke_few_args(s_next, 0); } return count; }
bool HHVM_FUNCTION(pcntl_signal_dispatch) { if (!signalHandlersInited()) return true; int *signaled = s_signal_handlers->signaled; for (int i = 0; i < _NSIG; i++) { if (signaled[i]) { signaled[i] = 0; if (s_signal_handlers->handlers.exists(i)) { vm_call_user_func(s_signal_handlers->handlers[i], make_packed_array(i)); } } } return true; }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->m_func; if (LIKELY(func->maybeIntercepted() == 0)) return true; Variant *h = get_intercept_handler(func->fullNameRef(), &func->maybeIntercepted()); if (!h) return true; Transl::VMRegAnchor _; PC savePc = g_vmContext->m_pc; Variant doneFlag = true; Variant called_on; if (ar->hasThis()) { called_on = Variant(ar->getThis()); } else if (ar->hasClass()) { // For static methods, give handler the name of called class called_on = Variant(const_cast<StringData*>(ar->getClass()->name())); } Array intArgs = CREATE_VECTOR5(ar->m_func->fullNameRef(), called_on, get_frame_args_with_ref(ar), h->asCArrRef()[1], ref(doneFlag)); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { Offset pcOff; ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff); assert(outer); frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals()); Stack& stack = g_vmContext->getStack(); stack.top() = (Cell*)(ar + 1); tvDup(ret.asTypedValue(), stack.allocTV()); g_vmContext->m_fp = outer; g_vmContext->m_pc = outer->m_func->unit()->at(pcOff); return false; } g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; return true; }
static void recv_cb(uv_udp_ext_t* udp_handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags) { auto* data = Native::data<UVUdpData>(udp_handle->udp_object_data); auto recvCallback = data->recvCallback; auto errorCallback = data->errorCallback; if(nread > 0){ if(!recvCallback.isNull()){ vm_call_user_func(recvCallback, make_packed_array( udp_handle->udp_object_data, sock_addr((struct sockaddr *) addr), sock_port((struct sockaddr *) addr), String(buf->base, nread, CopyString), (int64_t) flags ) ); } } else{ if(!errorCallback.isNull()){ vm_call_user_func(errorCallback, make_packed_array(udp_handle->udp_object_data, nread, (int64_t) flags)); } } delete buf->base; }
Variant f_iterator_apply(const Variant& obj, const Variant& func, const Array& params /* = null_array */) { CHECK_TRAVERSABLE_IMPL(obj, 0); Object pobj = get_traversable_object_iterator(obj); pobj->o_invoke_few_args(s_rewind, 0); int64_t count = 0; while (same(pobj->o_invoke_few_args(s_valid, 0), true)) { if (!same(vm_call_user_func(func, params), true)) { break; } ++count; pobj->o_invoke_few_args(s_next, 0); } return count; }
Variant do_callback(CVarRef cb, CArrRef args) { assert(!m_exception); try { return vm_call_user_func(cb, args); } catch (Object &e) { ObjectData *od = e.get(); od->incRefCount(); m_exception = od; m_phpException = true; } catch (Exception &e) { m_exception = e.clone(); m_phpException = false; } return uninit_null(); }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->m_func; if (LIKELY(func->maybeIntercepted() == 0)) return true; Variant *h = get_intercept_handler(func->fullNameRef(), &func->maybeIntercepted()); if (!h) return true; Transl::VMRegAnchor _; PC savePc = g_vmContext->m_pc; Offset pcOff; ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff); assert(outer); g_vmContext->m_fp = outer; g_vmContext->m_pc = outer->m_func->unit()->at(pcOff); try { Variant doneFlag = true; Variant obj = ar->hasThis() ? Variant(Object(ar->getThis())) : uninit_null(); Array intArgs = CREATE_VECTOR5(ar->m_func->fullNameRef(), obj, get_frame_args_with_ref(ar), h->asCArrRef()[1], ref(doneFlag)); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { frame_free_locals_inl_no_hook(ar, ar->m_func->numLocals()); Stack& stack = g_vmContext->getStack(); stack.top() = (Cell*)(ar + 1); tvDup(ret.asTypedValue(), stack.allocTV()); return false; } g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; } catch (...) { g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; g_vmContext->m_stack.top() = Stack::frameStackBase(ar); throw; } return true; }
static void send_cb(uv_udp_send_t* sr, int status) { send_req_t *req = (send_req_t *) sr; uv_udp_ext_t *udp_handle = (uv_udp_ext_t *) req->handle; auto* data = Native::data<UVUdpData>(udp_handle->udp_object_data); auto callback = data->sendCallback; if(!callback.isNull()){ vm_call_user_func(callback, make_packed_array( udp_handle->udp_object_data, sock_addr((struct sockaddr *) &req->addr), sock_port((struct sockaddr *) &req->addr), status ) ); } delete req->buf.base; delete req; }
void EventHook::RunUserProfiler(const ActRec* ar, int mode) { // Don't do anything if we are running the profiling function itself // or if we haven't set up a profiler. if (g_vmContext->m_executingSetprofileCallback || g_vmContext->m_setprofileCallback.isNull()) { return; } // Don't profile 86ctor, since its an implementation detail, // and we dont guarantee to call it if (ar->m_func->cls() && ar->m_func == ar->m_func->cls()->getCtor() && Func::isSpecial(ar->m_func->name())) { return; } Transl::VMRegAnchor _; ExecutingSetprofileCallbackGuard guard; Array params; Array frameinfo; if (mode == ProfileEnter) { params.append(s_enter); frameinfo.set(s_args, hhvm_get_frame_args(ar)); } else { params.append(s_exit); if (!g_vmContext->m_faults.empty()) { Fault fault = g_vmContext->m_faults.back(); if (fault.m_faultType == Fault::Type::UserException) { frameinfo.set(s_exception, fault.m_userException); } } else if (!ar->m_func->info() && !ar->m_func->isGenerator()) { // TODO (#1131400) This is wrong for builtins frameinfo.set(s_return, tvAsCVarRef(g_vmContext->m_stack.topTV())); } } params.append(VarNR(ar->m_func->fullName())); params.append(frameinfo); vm_call_user_func(g_vmContext->m_setprofileCallback, params); }
static Variant xml_call_handler(const req::ptr<XmlParser>& parser, const Variant& handler, const Array& args) { if (parser && handler.toBoolean()) { Variant retval; if (handler.isString() && !name_contains_class(handler.toString())) { if (!parser->object.isObject()) { retval = invoke(handler.toString().c_str(), args, -1); } else { retval = parser->object.toObject()-> o_invoke(handler.toString(), args); } } else if (is_callable(handler)) { vm_call_user_func(handler, args); } else { raise_warning("Handler is invalid"); } return retval; } return init_null(); }
static Variant xml_call_handler(XmlParser *parser, CVarRef handler, CArrRef args) { if (parser && handler) { Variant retval; if (handler.isString()) { if (!parser->object.isObject()) { retval = invoke(handler.toString().c_str(), args, -1); } else { retval = parser->object.toObject()-> o_invoke(handler.toString(), args); } } else if (handler.isArray() && handler.getArrayData()->size() == 2 && (handler[0].isString() || handler[0].isObject()) && handler[1].isString()) { vm_call_user_func(handler, args); } else { raise_warning("Handler is invalid"); } return retval; } return uninit_null(); }
static void sqlite3_do_callback(sqlite3_context *context, const Variant& callback, int argc, sqlite3_value **argv, bool is_agg) { Array params = Array::Create(); php_sqlite3_agg_context *agg_context = nullptr; if (is_agg) { agg_context = (php_sqlite3_agg_context *)sqlite3_aggregate_context (context, sizeof(php_sqlite3_agg_context)); params.appendRef(agg_context->context); params.append(agg_context->row_count); } for (int i = 0; i < argc; i++) { params.append(get_value(argv[i])); } Variant ret = vm_call_user_func(callback, params); if (!is_agg || !argv) { /* only set the sqlite return value if we are a scalar function, * or if we are finalizing an aggregate */ if (ret.isInteger()) { sqlite3_result_int(context, ret.toInt64()); } else if (ret.isNull()) { sqlite3_result_null(context); } else if (ret.isDouble()) { sqlite3_result_double(context, ret.toDouble()); } else { String sret = ret.toString(); sqlite3_result_text(context, sret.data(), sret.size(), SQLITE_TRANSIENT); } } else { /* we're stepping in an aggregate; the return value goes into * the context */ agg_context->context = ret; } }
Variant f_xbox_process_call_message(const String& msg) { Variant v = unserialize_from_string(msg); if (!v.isArray()) { raise_error("Error decoding xbox call message"); } Array arr = v.toArray(); if (arr.size() != 2 || !arr.exists(0) || !arr.exists(1)) { raise_error("Error decoding xbox call message"); } Variant fn = arr.rvalAt(0); if (fn.isArray()) { Array farr = fn.toArray(); if (!array_is_valid_callback(farr)) { raise_error("Error decoding xbox call message"); } } else if (!fn.isString()) { raise_error("Error decoding xbox call message"); } Variant args = arr.rvalAt(1); if (!args.isArray()) { raise_error("Error decoding xbox call message"); } return vm_call_user_func(fn, args.toArray()); }
static Variant xml_call_handler(const req::ptr<XmlParser>& parser, const Variant& handler, const Array& args) { if (parser && handler.toBoolean()) { Variant retval; if (handler.isString()) { if (!parser->object.isObject()) { retval = invoke(handler.toString().c_str(), args, -1); } else { retval = parser->object.toObject()-> o_invoke(handler.toString(), args); } } else if (handler.isArray() && handler.getArrayData()->size() == 2 && (handler.toCArrRef()[0].isString() || handler.toCArrRef()[0].isObject()) && handler.toCArrRef()[1].isString()) { vm_call_user_func(handler, args); } else { raise_warning("Handler is invalid"); } return retval; } return init_null(); }
static void idle_handle_callback(uv_idle_ext_t *idle_handle) { auto* data = Native::data<UVNativeData>(idle_handle->idle_object_data); vm_call_user_func(data->callback, make_packed_array(idle_handle->idle_object_data)); }
void heapgraphCallback(Array fields, const Variant& callback) { VMRegAnchor _; Array params; params.append(fields); vm_call_user_func(callback, params); }
size_t check_request_surprise() { auto& info = TI(); auto& p = info.m_reqInjectionData; auto const flags = fetchAndClearSurpriseFlags(); auto const do_timedout = (flags & TimedOutFlag) && !p.getDebuggerAttached(); auto const do_memExceeded = flags & MemExceededFlag; auto const do_memThreshold = flags & MemThresholdFlag; auto const do_signaled = flags & SignaledFlag; auto const do_cpuTimedOut = (flags & CPUTimedOutFlag) && !p.getDebuggerAttached(); auto const do_GC = flags & PendingGCFlag; // Start with any pending exception that might be on the thread. auto pendingException = info.m_pendingException; info.m_pendingException = nullptr; if (do_timedout) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { setSurpriseFlag(TimedOutFlag); } else { pendingException = generate_request_timeout_exception(); } } // Don't bother with the CPU timeout if we're already handling a wall timeout. if (do_cpuTimedOut && !do_timedout) { p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { setSurpriseFlag(CPUTimedOutFlag); } else { pendingException = generate_request_cpu_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { setSurpriseFlag(MemExceededFlag); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_memThreshold) { clearSurpriseFlag(MemThresholdFlag); if (!g_context->m_memThresholdCallback.isNull()) { VMRegAnchor _; try { vm_call_user_func(g_context->m_memThresholdCallback, empty_array()); } catch (Object& ex) { raise_error("Uncaught exception escaping mem Threshold callback: %s", ex.toString().data()); } } } if (do_GC) { VMRegAnchor _; if (RuntimeOption::EvalEnableGC) { MM().collect("surprise"); } else { MM().checkHeap("surprise"); } } if (do_signaled) { HHVM_FN(pcntl_signal_dispatch)(); } if (pendingException) { pendingException->throwException(); } return flags; }
static void event_http_request_cb(evhttp_request_t *request, void *data) { EventHttpRequestResourceData *resource_data = (EventHttpRequestResourceData *) data; evhttp_request_own((evhttp_request_t *) resource_data->getInternalResourceData()); vm_call_user_func(Object(resource_data->getCallback()), make_packed_array(Object(resource_data->getObjectData()), resource_data->getCallbackArg())); }
static int cmp_func(CVarRef v1, CVarRef v2, const void *data) { Variant *callback = (Variant *)data; return vm_call_user_func(*callback, make_packed_array(v1, v2)).toInt32(); }
static void xslt_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) { XSLTProcessorData *intern = nullptr; int error = 0; xsltTransformContextPtr tctxt = xsltXPathGetTransformContext (ctxt); if (tctxt == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n" ); error = 1; } else { intern = (XSLTProcessorData*)tctxt->_private; if (intern == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the internal object\n" ); error = 1; } else { if (intern->m_registerPhpFunctions == 0) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: PHP Object did not register PHP functions\n" ); error = 1; } } } xmlXPathObjectPtr obj; if (error == 1) { for (int i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } Array args; // Reverse order to pop values off ctxt stack for (int i = nargs - 2; i >= 0; i--) { Variant arg; obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: arg = String((char*)obj->stringval, CopyString); break; case XPATH_BOOLEAN: arg = (bool)obj->boolval; break; case XPATH_NUMBER: arg = (double)obj->floatval; break; case XPATH_NODESET: if (type == 1) { char *str = (char*)xmlXPathCastToString(obj); arg = String(str, CopyString); xmlFree(str); } else if (type == 2) { arg = Array::Create(); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (int j = 0; j < obj->nodesetval->nodeNr; j++) { // TODO: not sure this is the right thing to do. xmlNodePtr node = obj->nodesetval->nodeTab[j]; if (node->type == XML_ELEMENT_NODE) { Object element = newNode(s_DOMElement, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(element); } else if (node->type == XML_ATTRIBUTE_NODE) { Object attribute = newNode(s_DOMAttr, (xmlNodePtr)xmlCopyProp(nullptr, (xmlAttrPtr)node)); arg.toArrRef().append(attribute); } else if (node->type == XML_TEXT_NODE) { Object text = newNode(s_DOMText, (xmlNodePtr)xmlNewText(xmlNodeGetContent(node))); arg.toArrRef().append(text); } else { raise_warning("Unhandled node type '%d'", node->type); // Use a generic DOMNode as fallback for now. Object nodeobj = newNode(s_DOMNode, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(nodeobj); } } } } break; default: arg = String((char*)xmlXPathCastToString(obj), CopyString); } xmlXPathFreeObject(obj); args.prepend(arg); } obj = valuePop(ctxt); if (obj->stringval == nullptr) { raise_warning("Handler name must be a string"); xmlXPathFreeObject(obj); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); return; } String handler((char*)obj->stringval, CopyString); xmlXPathFreeObject(obj); if (!HHVM_FN(is_callable)(handler)) { raise_warning("Unable to call handler %s()", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else if (intern->m_registerPhpFunctions == 2 && !intern->m_registered_phpfunctions.exists(handler)) { raise_warning("Not allowed to call handler '%s()'", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { Variant retval = vm_call_user_func(handler, args); if (retval.isObject() && retval.getObjectData()->instanceof(s_DOMNode)) { ObjectData *retval_data = retval.asCObjRef().get(); xmlNode* nodep = Native::data<DOMNode>(retval_data)->nodep(); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); intern->m_usedElements.prepend(retval); } else if (retval.is(KindOfBoolean)) { valuePush(ctxt, xmlXPathNewBoolean(retval.toBoolean())); } else if (retval.isObject()) { raise_warning("A PHP Object cannot be converted to an XPath-string"); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { String sretval = retval.toString(); valuePush(ctxt, xmlXPathNewString((xmlChar*)sretval.data())); } } }
static void event_http_default_cb(evhttp_request_t *request, void *data) { EventHttpResourceData *resource_data = (EventHttpResourceData *) data; vm_call_user_func(Object(resource_data->getDefaultCallback()), make_packed_array(makeEventHttpRequestObject(request), resource_data->getDefaultCallbackArg())); }
static int cmp_func(CVarRef v1, CVarRef v2, const void *data) { Variant *callback = (Variant *)data; return vm_call_user_func(*callback, CREATE_VECTOR2(v1, v2)).toInt32(); }
void requestInit() override { vm_call_user_func(s_default_filters_register_func, empty_array_ref); }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->func(); if (LIKELY(func->maybeIntercepted() == 0)) return true; // Intercept only original generator / async function calls, not resumption. if (ar->resumed()) return true; Variant* h = get_intercept_handler(func->fullNameStr(), &func->maybeIntercepted()); if (!h) return true; /* * In production mode, only functions that we have assumed can be * intercepted during static analysis should actually be * intercepted. */ if (RuntimeOption::RepoAuthoritative && !RuntimeOption::EvalJitEnableRenameFunction) { if (!(func->attrs() & AttrInterceptable)) { raise_error("fb_intercept was used on a non-interceptable function (%s) " "in RepoAuthoritative mode", func->fullName()->data()); } } VMRegAnchor _; PC savePc = vmpc(); Variant doneFlag = true; Variant called_on; if (ar->hasThis()) { called_on = Variant(ar->getThis()); } else if (ar->hasClass()) { // For static methods, give handler the name of called class called_on = Variant(const_cast<StringData*>(ar->getClass()->name())); } Variant intArgs = PackedArrayInit(5) .append(VarNR(ar->func()->fullName())) .append(called_on) .append(get_frame_args_with_ref(ar)) .append(h->asCArrRef()[1]) .appendRef(doneFlag) .toArray(); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { Offset pcOff; ActRec* outer = g_context->getPrevVMState(ar, &pcOff); frame_free_locals_inl_no_hook<true>(ar, ar->func()->numLocals()); Stack& stack = vmStack(); stack.top() = (Cell*)(ar + 1); cellDup(*ret.asCell(), *stack.allocTV()); vmfp() = outer; vmpc() = outer ? outer->func()->unit()->at(pcOff) : nullptr; return false; } vmfp() = ar; vmpc() = savePc; return true; }
virtual void requestInit() { vm_call_user_func(s_default_filters_register_func, empty_array_ref); }