void TypeConstraint::verifyFail(const Func* func, int paramNum,
                                const TypedValue* tv) const {
  Transl::VMRegAnchor _;
  std::ostringstream fname;
  fname << func->fullName()->data() << "()";
  const StringData* tn = typeName();
  if (isSelf()) {
    selfToTypeName(func, &tn);
  } else if (isParent()) {
    parentToTypeName(func, &tn);
  }

  auto const givenType = describe_actual_type(tv);

  if (isExtended()) {
    // Extended type hints raise warnings instead of recoverable
    // errors for now, to ease migration (we used to not check these
    // at all at runtime).
    assert(nullable() &&
           "only nullable extended type hints are currently supported");
    raise_warning(
      "Argument %d to %s must be of type ?%s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  } else {
    raise_recoverable_error(
      "Argument %d passed to %s must be an instance of %s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  }
}
Exemple #2
0
void raise_recoverable_error(const char *fmt, ...) {
  std::string msg;
  va_list ap;
  va_start(ap, fmt);
  string_vsnprintf(msg, fmt, ap);
  va_end(ap);
  raise_recoverable_error(msg);
}
Exemple #3
0
void raise_return_typehint_error(const std::string& msg) {
  raise_recoverable_error(msg);
  if (RuntimeOption::EvalCheckReturnTypeHints >= 3 ||
      (RuntimeOption::RepoAuthoritative &&
       Repo::global().HardReturnTypeHints)) {
    raise_error("Error handler tried to recover from a return typehint "
                "violation");
  }
}
Exemple #4
0
void raise_return_typehint_error(const std::string& msg) {
  if (RuntimeOption::PHP7_EngineExceptions) {
    VMRegAnchor _;
    SystemLib::throwTypeErrorObject(msg);
  }
  raise_recoverable_error(msg);
  if (RuntimeOption::EvalCheckReturnTypeHints >= 3) {
    raise_error("Error handler tried to recover from a return typehint "
                "violation");
  }
}
Exemple #5
0
void raise_property_typehint_error(const std::string& msg, bool isSoft) {
  assertx(RuntimeOption::EvalCheckPropTypeHints > 0);

  if (RuntimeOption::EvalCheckPropTypeHints == 1 || isSoft) {
    raise_warning_unsampled(msg);
    return;
  }

  raise_recoverable_error(msg);
  if (RuntimeOption::EvalCheckPropTypeHints >= 3) {
    raise_error("Error handler tried to recover from a property typehint "
                "violation");
  }
}
Exemple #6
0
void TypeConstraint::verifyFail(const Func* func, int paramNum,
                                const TypedValue* tv) const {
  Transl::VMRegAnchor _;
  std::ostringstream fname;
  fname << func->fullName()->data() << "()";
  const StringData* tn = typeName();
  if (isSelf()) {
    selfToTypeName(func, &tn);
  } else if (isParent()) {
    parentToTypeName(func, &tn);
  }

  auto const givenType = describe_actual_type(tv);

  if (isExtended()) {
    if (isSoft()) {
      // Soft type hints raise warnings instead of recoverable
      // errors by design, to ease migration.
      raise_warning(
        "Argument %d passed to %s must be of type %s, %s given",
        paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType);
    } else if (isNullable()) {
      // This error message is slightly different from the normal case
      // (fullName() vs tn)
      raise_recoverable_error(
        "Argument %d passed to %s must be of type %s, %s given",
        paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType);
    } else {
      assert(false &&
        "Only nullable and soft extended type hints are currently implemented");
    }
  } else {
    raise_recoverable_error(
      "Argument %d passed to %s must be an instance of %s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  }
}
static req::ptr<File>
phpStreamOpenFilter(const char* sFilter,
                    const String& modestr,
                    int options,
                    const req::ptr<StreamContext>& context) {
  const char *mode = modestr.c_str();
  int rwMode = 0;
  if (strchr(mode, 'r') || strchr(mode, '+')) {
    rwMode |= k_STREAM_FILTER_READ;
  }
  if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
    rwMode |= k_STREAM_FILTER_WRITE;
  }

  String duppath(sFilter, CopyString);
  char *path = duppath.mutableData();
  char *p = strstr(path, "/resource=");
  if (!p) {
    raise_recoverable_error("No URL resource specified");
    return nullptr;
  }
  auto fp = File::Open(String(p + sizeof("/resource=") - 1, CopyString),
                       modestr, options, context);
  if (!fp) return nullptr;
  Resource fpres(fp);
  *p = 0;
  char *token = nullptr;
  p = strtok_r(path + 1, "/", &token);
  while (p) {
    if (!strncasecmp(p, "read=", sizeof("read=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("read=") - 1,
                               k_STREAM_FILTER_READ);
    } else if (!strncasecmp(p, "write=", sizeof("write=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("write=") - 1,
                               k_STREAM_FILTER_WRITE);
    } else {
      phpStreamApplyFilterList(fpres, p, rwMode);
    }
    p = strtok_r(nullptr, "/", &token);
  }
  return fp;
}
static File* phpStreamOpenFilter(const char* sFilter,
                                 const String& modestr,
                                 int options, const Variant& context) {
  const char *mode = modestr.c_str();
  int rwMode = 0;
  if (strchr(mode, 'r') || strchr(mode, '+')) {
    rwMode |= k_STREAM_FILTER_READ;
  }
  if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
    rwMode |= k_STREAM_FILTER_WRITE;
  }

  String duppath(sFilter, CopyString);
  char *path = duppath.bufferSlice().ptr;
  char *p = strstr(path, "/resource=");
  if (!p) {
    raise_recoverable_error("No URL resource specified");
    return nullptr;
  }
  Resource fpres = File::Open(String(p + sizeof("/resource=") - 1, CopyString),
                              modestr, options, context);
  if (fpres.isNull()) {
    return nullptr;
  }
  *p = 0;
  char *token = nullptr;
  p = strtok_r(path + 1, "/", &token);
  while (p) {
    if (!strncasecmp(p, "read=", sizeof("read=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("read=") - 1,
                               k_STREAM_FILTER_READ);
    } else if (!strncasecmp(p, "write=", sizeof("write=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("write=") - 1,
                               k_STREAM_FILTER_WRITE);
    } else {
      phpStreamApplyFilterList(fpres, p, rwMode);
    }
    p = strtok_r(nullptr, "/", &token);
  }
  return dynamic_cast<File*>(fpres.detach());
}
Exemple #9
0
void raise_typehint_error(const std::string& msg) {
  raise_recoverable_error(msg);
  if (RuntimeOption::RepoAuthoritative && Repo::global().HardTypeHints) {
    raise_error("Error handler tried to recover from typehint violation");
  }
}
Exemple #10
0
Variant c_Closure::t___unset(Variant name) {
  raise_recoverable_error("Closure object cannot have properties");
  return init_null();
}
Exemple #11
0
bool c_Closure::t___isset(Variant name) {
  raise_recoverable_error("Closure object cannot have properties");
  return false;
}
Exemple #12
0
Variant c_Closure::t___set(Variant member, Variant value) {
  raise_recoverable_error("Closure object cannot have properties");
  return init_null();
}
Exemple #13
0
static Variant eval_for_assert(ActRec* const curFP, const String& codeStr) {
  String prefixedCode = concat3("<?php return ", codeStr, ";");

  auto const oldErrorLevel =
    s_option_data->assertQuietEval ? HHVM_FN(error_reporting)(Variant(0)) : 0;
  SCOPE_EXIT {
    if (s_option_data->assertQuietEval) HHVM_FN(error_reporting)(oldErrorLevel);
  };

  auto const unit = g_context->compileEvalString(prefixedCode.get());
  if (unit == nullptr) {
    raise_recoverable_error("Syntax error in assert()");
    // Failure to compile the eval string doesn't count as an
    // assertion failure.
    return Variant(true);
  }

  if (!(curFP->func()->attrs() & AttrMayUseVV)) {
    throw_not_supported("assert()",
                        "assert called from non-varenv function");
  }

  if (!curFP->hasVarEnv()) {
    curFP->setVarEnv(VarEnv::createLocal(curFP));
  }
  auto varEnv = curFP->getVarEnv();

  if (curFP != vmfp()) {
    // If we aren't using FCallBuiltin, the stack frame of the call to assert
    // will be in middle of the code we are about to eval and our caller, whose
    // varEnv we want to use. The invokeFunc below will get very confused if
    // this is the case, since it will be using a varEnv that belongs to the
    // wrong function on the stack. So, we rebind it here, to match what
    // invokeFunc will expect.
    assert(!vmfp()->hasVarEnv());
    vmfp()->setVarEnv(varEnv);
    varEnv->enterFP(curFP, vmfp());
  }

  ObjectData* thiz = nullptr;
  Class* cls = nullptr;
  Class* ctx = curFP->func()->cls();
  if (ctx) {
    if (curFP->hasThis()) {
      thiz = curFP->getThis();
      cls = thiz->getVMClass();
    } else {
      cls = curFP->getClass();
    }
  }
  auto const func = unit->getMain(ctx);
  return Variant::attach(
    g_context->invokeFunc(
      func,
      init_null_variant,
      thiz,
      cls,
      varEnv,
      nullptr,
      ExecutionContext::InvokePseudoMain
    )
  );
}