Example #1
0
String debug_string_backtrace(bool skip) {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt;
    StringBuffer buf;
    bt = g_vmContext->debugBacktrace(skip);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists(s_class)) {
        buf.append(frame->get(s_class).toString());
        buf.append(frame->get(s_type).toString());
      }
      buf.append(frame->get(s_function).toString());
      buf.append("()");
      if (frame.exists(s_file)) {
        buf.append(" called at [");
        buf.append(frame->get(s_file).toString());
        buf.append(':');
        buf.append(frame->get(s_line).toString());
        buf.append(']');
      }
      buf.append('\n');
    }
    return buf.detach();
  } else {
    StackTrace st;
    return String(st.toString());
  }
}
Example #2
0
Variant HHVM_FUNCTION(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());
}
Example #3
0
void f_debug_print_backtrace() {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt = FrameInjection::GetBacktrace(true);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      StringBuffer buf;
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists("class")) {
        buf.append(frame->get("class").toString());
        buf.append(frame->get("type").toString());
      }
      buf.append(frame->get("function").toString());
      buf.append("()");
      if (frame.exists("file")) {
        buf.append(" called at [");
        buf.append(frame->get("file").toString());
        buf.append(':');
        buf.append(frame->get("line").toString());
        buf.append(']');
      }
      buf.append('\n');
      echo(buf.detach());
    }
  } else {
    StackTrace st;
    echo(String(st.toString()));
  }
}
Example #4
0
void ExtendedLogger::PrintStackTrace(FILE *f, CArrRef stackTrace,
                                     bool escape /* = false */,
                                     bool escapeMore /* = false */) {
  int i = 0;
  for (ArrayIter it(stackTrace); it; ++it, ++i) {
    if (i > 0) {
      fprintf(f, "%s", escape ? "\\n" : "\n");
    }
    Array frame = it.second().toArray();
    fprintf(f, "    #%d ", i);
    if (frame.exists(s_function)) {
      if (frame.exists(s_class)) {
        fprintf(f, "%s%s%s(), called ", frame[s_class].toString().c_str(),
                frame[s_type].toString().c_str(),
                frame[s_function].toString().c_str());
      } else {
        fprintf(f, "%s(), called ", frame[s_function].toString().c_str());
      }
    }
    fprintf(f, "at [%s:%" PRId64 "]", frame[s_file].toString().c_str(),
            frame[s_line].toInt64());
  }
  fprintf(f, escapeMore ? "\\n" : "\n");
  fflush(f);
}
Example #5
0
String debug_string_backtrace(bool skip, bool ignore_args /* = false */,
                              int limit /* = 0 */) {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt;
    StringBuffer buf;
    bt = g_context->debugBacktrace(skip, false, false, nullptr,
                                     ignore_args, limit);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists(s_class)) {
        buf.append(frame->get(s_class).toString());
        buf.append(frame->get(s_type).toString());
      }
      buf.append(frame->get(s_function).toString());
      buf.append("(");
      if (!ignore_args) {
        bool first = true;
        for (ArrayIter it = frame->get(s_args).begin(); !it.end(); it.next()) {
          if (!first) {
            buf.append(", ");
          } else {
            first = false;
          }
          try {
            buf.append(it.second().toString());
          } catch (FatalErrorException& fe) {
            buf.append(fe.getMessage());
          }
        }
      }
      buf.append(")");
      if (frame.exists(s_file)) {
        buf.append(" called at [");
        buf.append(frame->get(s_file).toString());
        buf.append(':');
        buf.append(frame->get(s_line).toString());
        buf.append(']');
      }
      buf.append('\n');
    }
    return buf.detach();
  } else {
    StackTrace st;
    return String(st.toString());
  }
}
Example #6
0
void StreamContext::mergeParams(const Array& params) {
  if (m_params.isNull()) {
    m_params = Array::Create();
  }
  const String& notification_key = String::FromCStr("notification");
  if (params.exists(notification_key)) {
    m_params.set(notification_key, params[notification_key]);
  }
  const String& options_key = String::FromCStr("options");
  if (params.exists(options_key)) {
    assert(params[options_key].isArray());
    mergeOptions(params[options_key].toArray());
  }
}
Example #7
0
String debug_string_backtrace(bool skip, bool ignore_args /* = false */,
                              int64_t limit /* = 0 */) {
  Array bt;
  StringBuffer buf;
  bt = createBacktrace(BacktraceArgs()
                       .skipTop(skip)
                       .ignoreArgs(ignore_args)
                       .setLimit(limit));
  int i = 0;
  for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
    Array frame = it.second().toArray();
    buf.append('#');
    buf.append(i);
    if (i < 10) buf.append(' ');
    buf.append(' ');
    if (frame.exists(s_class)) {
      buf.append(frame->get(s_class).toString());
      buf.append(frame->get(s_type).toString());
    }
    buf.append(frame->get(s_function).toString());
    buf.append("(");
    if (!ignore_args) {
      bool first = true;
      for (ArrayIter it(frame->get(s_args).toArray());
          !it.end();
          it.next()) {
        if (!first) {
          buf.append(", ");
        } else {
          first = false;
        }
        try {
          buf.append(it.second().toString());
        } catch (FatalErrorException& fe) {
          buf.append(fe.getMessage());
        }
      }
    }
    buf.append(")");
    if (frame.exists(s_file)) {
      buf.append(" called at [");
      buf.append(frame->get(s_file).toString());
      buf.append(':');
      buf.append(frame->get(s_line).toString());
      buf.append(']');
    }
    buf.append('\n');
  }
  return buf.detach();
}
Example #8
0
bool f_is_callable(CVarRef v, bool syntax /* = false */,
                   Variant name /* = null */) {
  if (v.isString()) {
    if (!name.isNull()) name = v;
    if (syntax) return true;

    string lowered = Util::toLower((const char *)v.toString());
    size_t c = lowered.find("::");
    if (c != 0 && c != string::npos && c+2 < lowered.size()) {
      string classname = lowered.substr(0, c);
      string methodname = lowered.substr(c+2);
      const ClassInfo *clsInfo = ClassInfo::FindClass(classname.c_str());
      if (clsInfo && clsInfo->isDeclared()) {
        return clsInfo->hasMethod(methodname.c_str());
      }
      return false;
    }

    return f_function_exists(v.toString());
  }

  if (v.is(KindOfArray)) {
    Array arr = v.toArray();
    if (arr.size() == 2 && arr.exists(0LL) && arr.exists(1LL)) {
      Variant v0 = arr.rvalAt(0LL);
      Variant v1 = arr.rvalAt(1LL);
      if (v0.is(KindOfObject)) {
        v0 = v0.toObject()->o_getClassName();
      }
      if (v0.isString() && v1.isString()) {
        if (!name.isNull()) {
          name = v0.toString() + "::" + v1.toString();
        }
        if (same(v0, "self") || same(v0, "parent")) {
          throw NotImplementedException("augmenting class scope info");
        }
        const ClassInfo *clsInfo = ClassInfo::FindClass(v0.toString());
        if (clsInfo && clsInfo->isDeclared()) {
          return clsInfo->hasMethod(v1.toString());
        }
        return false;
      }
    }
  }

  if (!name.isNull()) {
    name = v.toString();
  }
  return false;
}
Example #9
0
req::ptr<PDOResource> PDODriver::createResource(const String& datasource,
                                                const String& username,
                                                const String& password,
                                                const Array& options) {
  auto const rsrc = createResourceImpl();
  auto const& conn = rsrc->conn();

  conn->data_source = datasource.toCppString();
  conn->username = username.toCppString();
  conn->password = password.toCppString();

  if (options.exists(PDO_ATTR_AUTOCOMMIT)) {
    conn->auto_commit = options[PDO_ATTR_AUTOCOMMIT].toInt64();
  } else {
    conn->auto_commit = 1;
  }

  if (!conn->create(options)) {
    Array err;
    bool hasError = conn->fetchErr(nullptr, err);

    if (hasError && !err.empty()) {
      throw_pdo_exception(uninit_null(),
                          "[%" PRId64 "]: %s",
                          err[0].toInt64(), err[1].toString().data());
    }
    return nullptr;
  }
  return rsrc;
}
Example #10
0
Array TaintTracer::TraceFrameAsArray(Array frame) {
  if (frame.exists("function")) {
    frame.set("function", Trace(frame["function"].toString()));
  }
  if (frame.exists("class")) {
    frame.set("class", Trace(frame["class"].toString()));
  }
  if (frame.exists("type")) {
    frame.set("type", Trace(frame["type"].toString()));
  }
  if (frame.exists("file")) {
    frame.set("file", Trace(frame["file"].toString()));
  }

  return frame;
}
void FiberReferenceMap::unmarshal(Variant &dest, CVarRef src, char strategy) {
  if (dest.isArray() && src.isArray()) {
    switch (strategy) {
      case FiberAsyncFunc::GlobalStateIgnore:
        // do nothing
        break;
      case FiberAsyncFunc::GlobalStateOverwrite:
        if (src.isInitialized()) {
          dest = src.fiberUnmarshal(*this);
        }
        break;
      case FiberAsyncFunc::GlobalStateSkip: {
        Array arr = dest.toArray();
        for (ArrayIter iter(src); iter; ++iter) {
          Variant key = iter.first();
          if (!arr.exists(key)) {
            dest.set(key.fiberUnmarshal(*this),
                     ref(iter.secondRef().fiberUnmarshal(*this)));
          }
        }
        break;
      }
      default:
        raise_error("unknown strategy: %d", (int)strategy);
        break;
    }
  } else if (strategy != FiberAsyncFunc::GlobalStateIgnore) {
    if (src.isInitialized()) {
      dest = src.fiberUnmarshal(*this);
    }
  }
}
 bool registerFilter(const String& name, const String& class_name) {
   if (m_registeredFilters.exists(name)) {
     return false;
   }
   m_registeredFilters.add(name, class_name);
   return true;
 }
Example #13
0
Resource HHVM_FUNCTION(pagelet_server_task_start,
                       const String& url,
                       const Array& headers /* = null_array */,
                       const String& post_data /* = null_string */,
                       const Array& files /* = null_array */,
                       int64_t desired_timeout /* = 0 */) {
  String remote_host;
  Transport *transport = g_context->getTransport();
  // If a non-zero timeout is requested, use it and cap it at the remaining
  // request time.
  int remaining_time =
    ThreadInfo::s_threadInfo->m_reqInjectionData.getRemainingTime();
  int timeout = desired_timeout > 0 && desired_timeout <= remaining_time
    ? desired_timeout
    : remaining_time;

  if (transport) {
    remote_host = transport->getRemoteHost();
    if (!headers.exists(s_Host) && RuntimeOption::SandboxMode) {
      Array tmp = headers;
      tmp.set(s_Host, transport->getHeader("Host"));
      return PageletServer::TaskStart(url, tmp, remote_host,
                                      post_data, files, timeout);
    }
  }
  return PageletServer::TaskStart(url, headers, remote_host,
                                  post_data, files, timeout);
}
Example #14
0
static void php_array_merge_recursive(PointerSet &seen, bool check,
                                      Array &arr1, CArrRef arr2) {
  if (check) {
    if (seen.find((void*)arr1.get()) != seen.end()) {
      raise_warning("array_merge_recursive(): recursion detected");
      return;
    }
    seen.insert((void*)arr1.get());
  }

  for (ArrayIter iter(arr2); iter; ++iter) {
    Variant key(iter.first());
    CVarRef value(iter.secondRef());
    if (key.isNumeric()) {
      arr1.appendWithRef(value);
    } else if (arr1.exists(key, true)) {
      // There is no need to do toKey() conversion, for a key that is already
      // in the array.
      Variant &v = arr1.lvalAt(key, AccessFlags::Key);
      Array subarr1(v.toArray()->copy());
      php_array_merge_recursive(seen, v.isReferenced(), subarr1,
                                value.toArray());
      v.unset(); // avoid contamination of the value that was strongly bound
      v = subarr1;
    } else {
      arr1.addLval(key, true).setWithRef(value);
    }
  }

  if (check) {
    seen.erase((void*)arr1.get());
  }
}
bool BaseExecutionContext::onFatalError(const Exception &e) {
  recordLastError(e);
  const char *file = NULL;
  int line = 0;
  if (RuntimeOption::InjectedStackTrace) {
    const ExtendedException *ee = dynamic_cast<const ExtendedException *>(&e);
    if (ee) {
      ArrayPtr bt = ee->getBackTrace();
      if (!bt->empty()) {
        Array top = bt->rvalAt(0).toArray();
        if (top.exists("file")) file = top.rvalAt("file").toString();
        if (top.exists("line")) line = top.rvalAt("line");
      }
    }
  }
  if (RuntimeOption::AlwaysLogUnhandledExceptions) {
    Logger::Log(Logger::LogError, "HipHop Fatal error: ", e, file, line);
  }
  bool handled = false;
  if (RuntimeOption::CallUserHandlerOnFatals) {
    int errnum = ErrorConstants::FATAL_ERROR;
    handled = callUserErrorHandler(e, errnum, true);
  }
  if (!handled && !RuntimeOption::AlwaysLogUnhandledExceptions) {
    Logger::Log(Logger::LogError, "HipHop Fatal error: ", e, file, line);
  }
  return handled;
}
Example #16
0
void c_Continuation::copyContinuationVars(ActRec* fp) {
  // For functions that contain only named locals, we can copy TVs
  // right to the local space.
  static const StringData* thisStr = s_this.get();
  bool skipThis;
  if (fp->hasVarEnv()) {
    Stats::inc(Stats::Cont_CreateVerySlow);
    Array definedVariables = fp->getVarEnv()->getDefinedVariables();
    skipThis = definedVariables.exists(s_this, true);

    for (ArrayIter iter(definedVariables); !iter.end(); iter.next()) {
      dupContVar(iter.first().getStringData(),
                 const_cast<TypedValue *>(iter.secondRef().asTypedValue()));
    }
  } else {
    const Func *genFunc = actRec()->m_func;
    skipThis = genFunc->lookupVarId(thisStr) != kInvalidId;
    for (Id i = 0; i < genFunc->numNamedLocals(); ++i) {
      dupContVar(genFunc->localVarName(i), frame_local(fp, i));
    }
  }

  // If $this is used as a local inside the body and is not provided
  // by our containing environment, just prefill it here instead of
  // using InitThisLoc inside the body
  if (!skipThis && fp->hasThis()) {
    Id id = actRec()->m_func->lookupVarId(thisStr);
    if (id != kInvalidId) {
      tvAsVariant(frame_local(actRec(), id)) = fp->getThis();
    }
  }
}
Example #17
0
bool PDOSqliteConnection::create(const Array& options) {
  String filename = data_source.substr(0,1) == ":" ? String(data_source) :
                    File::TranslatePath(data_source);
  if (filename.empty()) {
    throw_pdo_exception(0, Array(),
                        "safe_mode/open_basedir prohibits opening %s",
                        data_source.c_str());
    return false;
  }

  if (sqlite3_open(filename.data(), &m_db) != SQLITE_OK) {
    handleError(__FILE__, __LINE__);
    return false;
  }

  sqlite3_set_authorizer(m_db, authorizer, NULL);

  long timeout = 60;
  if (options.exists(PDO_ATTR_TIMEOUT)) {
    timeout = options[PDO_ATTR_TIMEOUT].toInt64();
  }
  sqlite3_busy_timeout(m_db, timeout * 1000);

  return true;
}
Example #18
0
static void php_array_replace_recursive(PointerSet &seen, bool check,
                                        Array &arr1, CArrRef arr2) {
  if (check) {
    if (seen.find((void*)arr1.get()) != seen.end()) {
      raise_warning("array_replace_recursive(): recursion detected");
      return;
    }
    seen.insert((void*)arr1.get());
  }

  for (ArrayIter iter(arr2); iter; ++iter) {
    Variant key = iter.first();
    CVarRef value = iter.secondRef();
    if (arr1.exists(key, true) && value.isArray()) {
      Variant &v = arr1.lvalAt(key, AccessFlags::Key);
      if (v.isArray()) {
        Array subarr1 = v.toArray();
        const ArrNR& arr_value = value.toArrNR();
        php_array_replace_recursive(seen, v.isReferenced(), subarr1,
                                    arr_value);
        v = subarr1;
      } else {
        arr1.set(key, value, true);
      }
    } else {
      arr1.lvalAt(key, AccessFlags::Key).setWithRef(value);
    }
  }

  if (check) {
    seen.erase((void*)arr1.get());
  }
}
Example #19
0
static void getMethodNamesImpl(const Class* cls,
                               const Class* ctx,
                               Array& out) {

  // The order of these methods is so that the first ones win on
  // case insensitive name conflicts.

  auto const methods = cls->methods();
  auto const numMethods = cls->numMethods();

  for (Slot i = 0; i < numMethods; ++i) {
    auto const meth = methods[i];
    auto const declCls = meth->cls();
    auto addMeth = [&]() {
      auto const methName = Variant(meth->name());
      auto const lowerName = f_strtolower(methName.toString());
      if (!out.exists(lowerName)) {
        out.add(lowerName, methName);
      }
    };

    // Only pick methods declared in this class, in order to match
    // Zend's order.  Inherited methods will be inserted in the
    // recursive call later.
    if (declCls != cls) continue;

    // Skip generated, internal methods.
    if (meth->isGenerated()) continue;

    // Public methods are always visible.
    if ((meth->attrs() & AttrPublic)) {
      addMeth();
      continue;
    }

    // In anonymous contexts, only public methods are visible.
    if (!ctx) continue;

    // All methods are visible if the context is the class that
    // declared them.  If the context is not the declCls, protected
    // methods are visible in context classes related the declCls.
    if (declCls == ctx ||
        ((meth->attrs() & AttrProtected) &&
         (ctx->classof(declCls) || declCls->classof(ctx)))) {
      addMeth();
    }
  }

  // Now add the inherited methods.
  if (auto const parent = cls->parent()) {
    getMethodNamesImpl(parent, ctx, out);
  }

  // Add interface methods that the class may not have implemented yet.
  for (auto& iface : cls->declInterfaces()) {
    getMethodNamesImpl(iface.get(), ctx, out);
  }
}
Example #20
0
String pdo_attr_strval(const Array& options, int opt, const char *def){
    if(options.exists(opt)){
        return options[opt].toString();
    }
    if(def){
        return def;
    }
    return String();
}
Example #21
0
Variant f_strtr(CStrRef str, CVarRef from, CVarRef to /* = null_variant */) {
  if (str.empty()) {
    return str;
  }

  if (!to.isNull()) {
    return StringUtil::Translate(str, from.toString(), to.toString());
  }

  if (!from.is(KindOfArray)) {
    throw_invalid_argument("2nd argument: (not array)");
    return false;
  }

  int maxlen = 0;
  int minlen = -1;
  Array arr = from.toArray();
  for (ArrayIter iter(arr); iter; ++iter) {
    String search = iter.first();
    int len = search.size();
    if (len < 1) return false;
    if (maxlen < len) maxlen = len;
    if (minlen == -1 || minlen > len) minlen = len;
  }

  const char *s = str.data();
  int slen = str.size();
  char *key = (char *)malloc(maxlen+1);

  StringBuffer result(slen);
  for (int pos = 0; pos < slen; ) {
    if ((pos + maxlen) > slen) {
      maxlen = slen - pos;
    }
    bool found = false;
    memcpy(key, s + pos, maxlen);
    for (int len = maxlen; len >= minlen; len--) {
      key[len] = 0;
      if (arr.exists(key)) {
        String replace = arr[key].toString();
        if (!replace.empty()) {
          result += replace;
        }
        pos += len;
        found = true;
        break;
      }
    }
    if (!found) {
      result += s[pos++];
    }
  }
  free(key);

  return result.detach();
}
Example #22
0
std::pair<String, int> ExtendedException::getFileAndLine() const {
  String file = empty_string();
  int line = 0;
  Array bt = getBacktrace();
  if (!bt.empty()) {
    Array top = bt.rvalAt(0).toArray();
    if (top.exists(s_file)) file = top.rvalAt(s_file).toString();
    if (top.exists(s_line)) line = top.rvalAt(s_line).toInt64();
  }
  return std::make_pair(file, line);
}
Example #23
0
static bool hippo_mongo_driver_manager_apply_rc(mongoc_uri_t *uri, const Array options)
{
	mongoc_read_concern_t *new_rc;
	const mongoc_read_concern_t *old_rc;
	const char *rc_str = NULL;

	if (!(old_rc = mongoc_uri_get_read_concern(uri))) {
		throw MongoDriver::Utils::throwRunTimeException("mongoc_uri_t does not have a read concern");

		return false;
	}

	if (options.size() == 0) {
		return true;
	}

	if (
		!options.exists(s_MongoDBDriverManager_readConcernLevel) &&
		!options.exists(s_MongoDBDriverManager_readconcernlevel)
	) {
		return true;
	}

	new_rc = mongoc_read_concern_copy(old_rc);

	if (options.exists(s_MongoDBDriverManager_readconcernlevel) && options[s_MongoDBDriverManager_readconcernlevel].isString()) {
		rc_str = options[s_MongoDBDriverManager_readconcernlevel].toString().c_str();
	}
	if (options.exists(s_MongoDBDriverManager_readConcernLevel) && options[s_MongoDBDriverManager_readConcernLevel].isString()) {
		rc_str = options[s_MongoDBDriverManager_readConcernLevel].toString().c_str();
	}

	if (rc_str) {
		mongoc_read_concern_set_level(new_rc, rc_str);
	}

	mongoc_uri_set_read_concern(uri, new_rc);
	mongoc_read_concern_destroy(new_rc);

	return true;
}
Example #24
0
Variant ArrayUtil::StringUnique(const Array& input) {
  Array seenValues;
  Array ret = Array::Create();
  for (ArrayIter iter(input); iter; ++iter) {
    auto const str = tvCastToString(iter.secondVal());
    if (!seenValues.exists(str)) {
      seenValues.set(str, 1);
      ret.set(iter.first(), iter.secondVal());
    }
  }
  return ret;
}
Example #25
0
static void CopyHeaderVariables(Array& server,
                                const HeaderMap& headers) {
    static std::atomic<int> badRequests(-1);

    std::vector<std::string> badHeaders;
    for (auto const& header : headers) {
        auto const& key = header.first;
        auto const& values = header.second;
        auto normalizedKey = s_HTTP_ +
                             string_replace(f_strtoupper(key), s_dash,
                                            s_underscore);

        // Detect suspicious headers.  We are about to modify header names for
        // the SERVER variable.  This means that it is possible to deliberately
        // cause a header collision, which an attacker could use to sneak a
        // header past a proxy that would either overwrite or filter it
        // otherwise.  Client code should use apache_request_headers() to
        // retrieve the original headers if they are security-critical.
        if (RuntimeOption::LogHeaderMangle != 0 && server.exists(normalizedKey)) {
            badHeaders.push_back(key);
        }

        if (!values.empty()) {
            // When a header has multiple values, we always take the last one.
            server.set(normalizedKey, String(values.back()));
        }
    }

    if (!badHeaders.empty()) {
        auto reqId = badRequests.fetch_add(1, std::memory_order_acq_rel) + 1;
        if (!(reqId % RuntimeOption::LogHeaderMangle)) {
            std::string badNames = folly::join(", ", badHeaders);
            std::string allHeaders;

            const char* separator = "";
            for (auto const& header : headers) {
                for (auto const& value : header.second) {
                    folly::toAppend(separator, header.first, ": ", value,
                                    &allHeaders);
                    separator = "\n";
                }
            }

            Logger::Warning(
                "HeaderMangle warning: "
                "The header(s) [%s] overwrote other headers which mapped to the same "
                "key. This happens because PHP normalises - to _, ie AN_EXAMPLE "
                "and AN-EXAMPLE are equivalent. You should treat this as "
                "malicious. All headers from this request:\n%s",
                badNames.c_str(), allHeaders.c_str());
        }
    }
}
void BaseExecutionContext::handleError(const std::string &msg,
                                       int errnum,
                                       bool callUserHandler,
                                       ErrorThrowMode mode,
                                       const std::string &prefix) {
  SYNC_VM_REGS_SCOPED();

  int newErrorState = ErrorRaised;
  switch (getErrorState()) {
  case ErrorRaised:
  case ErrorRaisedByUserHandler:
    return;
  case ExecutingUserHandler:
    newErrorState = ErrorRaisedByUserHandler;
    break;
  default:
    break;
  }
  ErrorStateHelper esh(this, newErrorState);
  ExtendedException ee(msg);
  recordLastError(ee, errnum);
  bool handled = false;
  if (callUserHandler) {
    handled = callUserErrorHandler(ee, errnum, false);
  }
  if (mode == AlwaysThrow || (mode == ThrowIfUnhandled && !handled)) {
    try {
      if (!Eval::Debugger::InterruptException(String(msg))) return;
    } catch (const Eval::DebuggerClientExitException &e) {}
    throw FatalErrorException(msg.c_str());
  }
  if (!handled &&
      (RuntimeOption::NoSilencer ||
       (getErrorReportingLevel() & errnum) != 0)) {
    try {
      if (!Eval::Debugger::InterruptException(String(msg))) return;
    } catch (const Eval::DebuggerClientExitException &e) {}

    const char *file = NULL;
    int line = 0;
    if (RuntimeOption::InjectedStackTrace) {
      ArrayPtr bt = ee.getBackTrace();
      if (!bt->empty()) {
        Array top = bt->rvalAt(0).toArray();
        if (top.exists("file")) file = top.rvalAt("file").toString();
        if (top.exists("line")) line = top.rvalAt("line");
      }
    }

    Logger::Log(Logger::LogError, prefix.c_str(), ee, file, line);
  }
}
Example #27
0
Variant ArrayUtil::StringUnique(CArrRef input) {
  Array seenValues;
  Array ret = Array::Create();
  for (ArrayIter iter(input); iter; ++iter) {
    CVarRef entry(iter.secondRef());
    String str(entry.toString());
    if (!seenValues.exists(str)) {
      seenValues.set(str, 1);
      ret.set(iter.first(), entry);
    }
  }
  return ret;
}
Example #28
0
std::string ExtendedLogger::StringOfStackTrace(CArrRef stackTrace) {
  std::ostringstream res;
  int i = 0;
  for (ArrayIter it(stackTrace); it; ++it, ++i) {
    Array frame = it.second().toArray();
    res << "    #" << i << " ";
    if (frame.exists("function")) {
      if (frame.exists("class")) {
        res << frame["class"].toString().c_str()
            << frame["type"].toString().c_str()
            << frame["function"].toString().c_str()
            << "(), called ";
      } else {
        res << frame["function"].toString().c_str()
            << "(), called ";
      }
    }
    res << "at [" << frame["file"].toString().c_str()
        << ":" << frame["line"].toInt64() << "]\n";
  }
  std::string buff(res.str());
  return buff;
}
Example #29
0
std::string ExtendedLogger::StringOfFrame(const Array& frame, int i, bool escape) {
  std::ostringstream ss;

  if (i > 0) {
    ss << (escape ? "\\n" : "\n");
  }
  ss << "    #" << i << " ";
  if (frame.exists(s_function)) {
    if (frame.exists(s_class)) {
      ss << frame[s_class].toString().c_str()
         << frame[s_type].toString().c_str()
         << frame[s_function].toString().c_str()
         << "(), called ";
    } else {
      ss << frame[s_function].toString().c_str()
         << "(), called ";
    }
  }
  ss << "at [" << frame[s_file].toString().c_str()
     << ":" << frame[s_line].toInt64() << "]";

  return ss.str();
}
File* HttpStreamWrapper::open(CStrRef filename, CStrRef mode,
                              int options, CVarRef context) {
  if (RuntimeOption::ServerHttpSafeMode) {
    return nullptr;
  }

  if (strncmp(filename.data(), "http://",  sizeof("http://")  - 1) &&
      strncmp(filename.data(), "https://", sizeof("https://") - 1)) {
    return nullptr;
  }

  std::unique_ptr<UrlFile> file;
  StreamContext *ctx = !context.isResource() ? nullptr :
                        context.toResource().getTyped<StreamContext>();
  if (!ctx || ctx->m_options.isNull() || ctx->m_options[s_http].isNull()) {
    file = std::unique_ptr<UrlFile>(NEWOBJ(UrlFile)());
  } else {
    Array opts = ctx->m_options[s_http].toArray();
    String method = s_GET;
    if (opts.exists(s_method)) {
      method = opts[s_method].toString();
    }
    Array headers;
    if (opts.exists(s_header)) {
      Array lines = StringUtil::Explode(
        opts[s_header].toString(), "\r\n").toArray();
      for (ArrayIter it(lines); it; ++it) {
        Array parts = StringUtil::Explode(
          it.second().toString(), ": ").toArray();
        headers.set(parts.rvalAt(0), parts.rvalAt(1));
      }
    }
    static const StaticString s_user_agent("user_agent");
    static const StaticString s_User_Agent("User-Agent");
    if (opts.exists(s_user_agent) && !headers.exists(s_User_Agent)) {
      headers.set(s_User_Agent, opts[s_user_agent]);
    }
    int max_redirs = 20;
    if (opts.exists(s_max_redirects)) {
      max_redirs = opts[s_max_redirects].toInt64();
    }
    int timeout = -1;
    if (opts.exists(s_timeout)) {
      timeout = opts[s_timeout].toInt64();
    }
    file = std::unique_ptr<UrlFile>(NEWOBJ(UrlFile)(method.data(), headers,
                                                    opts[s_content].toString(),
                                                    max_redirs, timeout));
  }
  bool ret = file->open(filename, mode);
  if (!ret) {
    raise_warning("Failed to open %s (%s)", filename.data(),
                  file->getLastError().c_str());
    return nullptr;
  }
  return file.release();
}