Variant HHVM_FUNCTION(serialize_memoize_param, const Variant& param) { // Memoize throws in the emitter if any function parameters are references, so // we can just assert that the param is cell here const auto& cell_param = *tvAssertCell(param.asTypedValue()); auto type = param.getType(); if (type == KindOfInt64) { return param; } else if (type == KindOfUninit || type == KindOfNull) { return s_empty; } else if (type == KindOfBoolean) { return param.asBooleanVal() ? s_true : s_false; } else if (type == KindOfString) { auto str = param.asCStrRef(); if (str.empty()) { return s_emptyStr; } else if (str.charAt(0) > '9') { // If it doesn't start with a number, then we know it can never collide // with an int or any of our constants, so it's fine as is return param; } } else if (isContainer(cell_param) && getContainerSize(cell_param) == 0) { return s_emptyArr; } return fb_compact_serialize(param, FBCompactSerializeBehavior::MemoizeParam); }
string& SourceRootInfo::initPhpRoot() { SystemGlobals *g = (SystemGlobals*)get_global_variables(); Variant &server = g->GV(_SERVER); Variant v = server.rvalAt("PHP_ROOT"); if (v.isString()) { *s_phproot.getCheck() = string(v.asCStrRef().data()) + string("/"); } else { // Our best guess at the source root. *s_phproot.getCheck() = GetCurrentSourceRoot(); } return *s_phproot.getCheck(); }
Variant HHVM_FUNCTION(mcrypt_get_block_size, const String& cipher, const Variant& module /* = null_string */) { MCRYPT td = mcrypt_module_open((char*)cipher.data(), (char*)MCG(algorithms_dir).data(), (char*)module.asCStrRef().data(), (char*)MCG(modes_dir).data()); if (td == MCRYPT_FAILED) { MCRYPT_OPEN_MODULE_FAILED("mcrypt_get_block_size"); return false; } int64_t ret = mcrypt_enc_get_block_size(td); mcrypt_module_close(td); return ret; }
bool f_stream_is_local(const Variant& stream_or_url) { if (stream_or_url.isString()) { auto wrapper = Stream::getWrapperFromURI(stream_or_url.asCStrRef()); return wrapper->m_isLocal; } else if (stream_or_url.isResource()) { File* file = dynamic_cast<File*>(stream_or_url.asCResRef().get()); if (!file) { raise_warning("supplied resource is not a valid stream resource"); return false; } return file->m_isLocal; } // Zend returns true for random data types... return true; }
void HHVM_METHOD(ZMQCert, __construct, const Variant& filename) { auto cert = Native::data<ZMQCert>(this_); if (filename.isNull()) { cert->zcert = zcert_new(); if (!cert->zcert) { throwExceptionClass(s_ZMQCertExceptionClass, "Failed to create the underlying zcert object. Is libsodium installed?", PHP_ZMQ_INTERNAL_ERROR); } } else { cert->zcert = zcert_load(filename.asCStrRef().c_str()); if (!cert->zcert) { throwExceptionClassFmt(s_ZMQCertExceptionClass, "Failed to load the certificate from {}", filename.asCStrRef()); } } }
int libxml_streams_IO_read(void* context, char* buffer, int len) { ITRACE(1, "libxml_IO_read({}, {}, {})\n", context, (void*)buffer, len); Trace::Indent _i; Resource stream(static_cast<ResourceData*>(context)); assert(len >= 0); Variant ret = HHVM_FN(fread)(stream, len); if (ret.isString()) { const String& str = ret.asCStrRef(); if (str.size() <= len) { std::memcpy(buffer, str.data(), str.size()); return str.size(); } } return -1; }
void RepoQuery::getTypedValue(int iCol, TypedValue& tv) { const void* blob; size_t size; getBlob(iCol, blob, size); tvWriteUninit(&tv); if (size > 0) { String s = String((const char*)blob, size, CopyString); Variant v = unserialize_from_string(s); if (v.isString()) { v = String(StringData::GetStaticString(v.asCStrRef().get())); } else if (v.isArray()) { v = Array(ArrayData::GetScalarArray(v.asCArrRef().get())); } else { // Serialized variants and objects shouldn't ever make it into the repo. assert(!IS_REFCOUNTED_TYPE(v.getType())); } tvAsVariant(&tv) = v; } }
Variant HHVM_FUNCTION(bzopen, const Variant& filename, const String& mode) { if (mode != s_r && mode != s_w) { raise_warning( "'%s' is not a valid mode for bzopen(). " "Only 'w' and 'r' are supported.", mode.data() ); return false; } BZ2File *bz; if (filename.isString()) { if (filename.asCStrRef().empty()) { raise_warning("filename cannot be empty"); return false; } bz = newres<BZ2File>(); bool ret = bz->open(File::TranslatePath(filename.toString()), mode); if (!ret) { raise_warning("%s", folly::errnoStr(errno).c_str()); return false; } } else { if (!filename.isResource()) { raise_warning("first parameter has to be string or file-resource"); return false; } PlainFile* f = filename.toResource().getTyped<PlainFile>(); if (!f) { return false; } std::string stream_mode = f->getMode(); int stream_mode_len = stream_mode.length(); if (stream_mode_len != 1 && !(stream_mode_len == 2 && stream_mode.find('b') != std::string::npos)) { raise_warning("cannot use stream opened in mode '%s'", stream_mode.c_str()); return false; } else if (stream_mode_len == 1 && stream_mode[0] != 'r' && stream_mode[0] != 'w' && stream_mode[0] != 'a' && stream_mode[0] != 'x') { raise_warning("cannot use stream opened in mode '%s'", stream_mode.c_str()); return false; } const char rw_mode = stream_mode[0]; if (mode == s_r && rw_mode != 'r') { raise_warning("cannot write to a stream opened in read only mode"); return false; } else if (mode == s_w && rw_mode != 'w' && rw_mode != 'a' && rw_mode != 'x') { raise_warning("cannot read from a stream opened in write only mode"); return false; } bz = newres<BZ2File>(f); } Resource handle(bz); return handle; }
Variant HHVM_FUNCTION(proc_open, const String& cmd, const Array& descriptorspec, VRefParam pipesParam, const Variant& cwd /* = uninit_variant */, const Variant& env /* = uninit_variant */, const Variant& other_options /* = uninit_variant */) { if (RuntimeOption::WhitelistExec && !check_cmd(cmd.data())) { return false; } if (cmd.size() != strlen(cmd.c_str())) { raise_warning("NULL byte detected. Possible attack"); return false; } Variant pipes(pipesParam, Variant::WithRefBind{}); std::vector<DescriptorItem> items; std::string scwd = ""; if (!cwd.isNull() && cwd.isString() && !cwd.asCStrRef().empty()) { scwd = cwd.asCStrRef().c_str(); } else if (!g_context->getCwd().empty()) { scwd = g_context->getCwd().c_str(); } Array enva; if (env.isNull()) { if (is_cli_mode()) { enva = cli_env(); } else { // Build out an environment that conceptually matches what we'd // see if we were to iterate the environment and call getenv() // for each name. // Env vars defined in the hdf file go in first for (const auto& envvar : RuntimeOption::EnvVariables) { enva.set(String(envvar.first), String(envvar.second)); } // global environment overrides the hdf for (char **env = environ; env && *env; env++) { char *p = strchr(*env, '='); if (p) { String name(*env, p - *env, CopyString); String val(p + 1, CopyString); enva.set(name, val); } } } // and then any putenv() changes take precedence for (ArrayIter iter(g_context->getEnvs()); iter; ++iter) { enva.set(iter.first(), iter.second()); } } else { enva = env.toArray(); } #ifdef _WIN32 PROCESS_INFORMATION pi; HANDLE childHandle; STARTUPINFO si; BOOL newprocok; SECURITY_ATTRIBUTES security; DWORD dwCreateFlags = 0; char *command_with_cmd; UINT old_error_mode; char cur_cwd[MAXPATHLEN]; bool suppress_errors = false; bool bypass_shell = false; if (!other_options.isNull() && other_options.isArray()) { auto arr = other_options.asCArrRef(); if (arr.exists(String("suppress_errors", CopyString), true)) { auto v = arr[String("suppress_errors", CopyString)]; if ((v.isBoolean() && v.asBooleanVal()) || (v.isInteger() && v.asInt64Val())) { suppress_errors = true; } } if (arr.exists(String("bypass_shell", CopyString), true)) { auto v = arr[String("bypass_shell", CopyString)]; if ((v.isBoolean() && v.asBooleanVal()) || (v.isInteger() && v.asInt64Val())) { bypass_shell = true; } } } /* we use this to allow the child to inherit handles */ memset(&security, 0, sizeof(security)); security.nLength = sizeof(security); security.bInheritHandle = true; security.lpSecurityDescriptor = nullptr; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (!pre_proc_open(descriptorspec, items)) return false; /* redirect stdin/stdout/stderr if requested */ for (size_t i = 0; i < items.size(); i++) { switch (items[i].index) { case 0: si.hStdInput = items[i].childend; break; case 1: si.hStdOutput = items[i].childend; break; case 2: si.hStdError = items[i].childend; break; } } memset(&pi, 0, sizeof(pi)); if (suppress_errors) { old_error_mode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); } dwCreateFlags = NORMAL_PRIORITY_CLASS; if (!RuntimeOption::ServerExecutionMode()) { dwCreateFlags |= CREATE_NO_WINDOW; } char *envp = build_envp(enva); if (bypass_shell) { newprocok = CreateProcess( nullptr, strdup(cmd.c_str()), &security, &security, TRUE, dwCreateFlags, envp, scwd.c_str(), &si, &pi); } else { std::string command_with = "cmd.exe /c "; command_with += cmd.toCppString(); newprocok = CreateProcess( nullptr, strdup(command_with.c_str()), &security, &security, TRUE, dwCreateFlags, envp, scwd.c_str(), &si, &pi); } free(envp); if (suppress_errors) { SetErrorMode(old_error_mode); } if (newprocok == FALSE) { DWORD dw = GetLastError(); char* msg; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, nullptr); /* clean up all the descriptors */ for (size_t i = 0; i < items.size(); i++) { CloseHandle(items[i].childend); if (items[i].parentend) { CloseHandle(items[i].parentend); } } raise_warning("CreateProcess failed, error code - %u: %s", dw, msg); LocalFree(msg); return false; } childHandle = pi.hProcess; DWORD child = pi.dwProcessId; CloseHandle(pi.hThread); return post_proc_open(cmd, pipes, enva, items, (pid_t)child, childHandle); #else pid_t child; if (LightProcess::Available()) { // light process available // there is no need to do any locking, because the forking is delegated // to the light process if (!pre_proc_open(descriptorspec, items)) return false; const int item_size = items.size(); std::vector<int> created; created.reserve(item_size); std::vector<int> intended; intended.reserve(item_size); for (int i = 0; i < item_size; i++) { const auto& item = items[i]; created.push_back(item.childend); intended.push_back(item.index); } std::vector<std::string> envs; for (ArrayIter iter(enva); iter; ++iter) { StringBuffer nvpair; nvpair.append(iter.first().toString()); nvpair.append('='); nvpair.append(iter.second().toString()); std::string tmp = nvpair.detach().c_str(); if (tmp.find('\n') == std::string::npos) { envs.push_back(tmp); } } child = LightProcess::proc_open(cmd.c_str(), created, intended, scwd.c_str(), envs); assert(child); return post_proc_open(cmd, pipes, enva, items, child); } else { /* the unix way */ Lock lock(DescriptorItem::s_mutex); if (!pre_proc_open(descriptorspec, items)) return false; child = fork(); if (child) { // the parent process return post_proc_open(cmd, pipes, enva, items, child); } } assert(child == 0); /* this is the child process */ /* close those descriptors that we just opened for the parent stuff, * dup new descriptors into required descriptors and close the original * cruft */ for (auto& item : items) { item.dupChild(); } if (scwd.length() > 0 && chdir(scwd.c_str())) { // chdir failed, the working directory remains unchanged } std::vector<String> senvs; // holding those char * char **envp = build_envp(enva, senvs); execle("/bin/sh", "sh", "-c", cmd.data(), nullptr, envp); free(envp); _exit(127); #endif }
void ZMQSocketData::set(ZMQSocketData* sock, int64_t type, const Variant& persistentId) { if (sock->ctx->is_persistent && !persistentId.isNull()) { s_persistent_socket_list[std::pair<int64_t, const char*>(type, persistentId.asCStrRef().c_str())] = sock; } }