bool ConcurrentTableSharedStore::get(CStrRef key, Variant &value) {
  const StoreValue *sval;
  SharedVariant *svar = nullptr;
  ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree ||
                                m_lockingFlag);
  bool expired = false;
  bool promoteObj = false;
  {
    Map::const_accessor acc;
    if (!m_vars.find(acc, key.data())) {
      log_apc(std_apc_miss);
      return false;
    } else {
      sval = &acc->second;
      if (sval->expired()) {
        // Because it only has a read lock on the data, deletion from
        // expiration has to happen after the lock is released
        expired = true;
      } else {
        if (!sval->inMem()) {
          std::lock_guard<SmallLock> sval_lock(sval->lock);

          if (!sval->inMem()) {
            svar = unserialize(key, sval);
            if (!svar) return false;
          } else {
            svar = sval->var;
          }
        } else {
          svar = sval->var;
        }

        if (apcExtension::AllowObj && svar->is(KindOfObject)) {
          // Hold ref here for later promoting the object
          svar->incRef();
          promoteObj = true;
        }
        value = svar->toLocal();
        stats_on_get(key.get(), svar);
      }
    }
  }
  if (expired) {
    log_apc(std_apc_miss);
    eraseImpl(key, true);
    return false;
  }
  log_apc(std_apc_hit);

  if (promoteObj)  {
    handlePromoteObj(key, svar, value);
    // release the extra ref
    svar->decRef();
  }
  return true;
}
예제 #2
0
UserStreamWrapper::UserStreamWrapper(CStrRef name, CStrRef clsname) :
  m_name(name) {
  m_cls = Unit::loadClass(clsname.get());
  if (!m_cls) {
    throw InvalidArgumentException(0, "Undefined class '%s'", clsname.data());
  }
  // There is a third param in Zend to stream_wrapper_register() which could
  // affect that when we add that param
  m_isLocal = true;
}
예제 #3
0
bool f_defined(CStrRef name, bool autoload /* = true */) {
  if (!name.get()) return false;
  const char *data = name.data();
  int len = name.length();
  char *colon;
  if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
    // class constant
    int classNameLen = colon - data;
    char *constantName = colon + 2;
    String className(data, classNameLen, CopyString);

    // translate "self" or "parent"
    if (className == "self") {
      String this_class = g_vmContext->getContextClassName();
      if (this_class.empty()) {
        throw FatalErrorException("Cannot access self:: "
          "when no class scope is active");
      } else {
        className = this_class;
      }
    } else if (className == "parent") {
      String parent_class = g_vmContext->getParentContextClassName();
      if (parent_class.empty()) {
        throw FatalErrorException("Cannot access parent");
      } else {
        className = parent_class;
      }
    }
    if (class_exists(className)) { // taking care of volatile class
      const ClassInfo *info;
      for (String parentClass = className;
           !parentClass.empty();
           parentClass = info->getParentClass()) {
        info = ClassInfo::FindClass(parentClass);
        if (!info) {
          assert(false);
        }
        if (info->hasConstant(constantName)) return true;
      }
      return false;
    } else {
      return false;
    }
  } else {
    // system/uniquely defined scalar constant
    if (ClassInfo::FindConstant(name)) return true;
    if (g_vmContext->defined(name)) {
      return true;
    }
    if (!autoload || !AutoloadHandler::s_instance->autoloadConstant(name)) {
      return false;
    }
    return g_vmContext->defined(name);
  }
}
예제 #4
0
int ThreadSharedVariant::getIndex(CStrRef key) {
  ASSERT(is(KindOfArray));
  if (getIsVector()) return -1;
  StringData *sd = key.get();
  if (RuntimeOption::ApcUseGnuMap) {
    StringDataToIntMap::const_iterator it = m_data.gnuMap->strMap->find(sd);
    if (it == m_data.gnuMap->strMap->end()) return -1;
    return it->second;
  }
  return m_data.map->indexOf(sd);
}
예제 #5
0
void TaintWarning::WarnIfTainted(CStrRef s, const taint_t bit) {
  const TaintData& td = s.get()->getTaintDataRefConst();
  if (!(td.getTaint() & bit)) { return; }

  bool force_warning = false;
  std::string buf, aux;

  buf = "Using a ";
  switch (bit) {
    case TAINT_BIT_HTML:
      buf += "HTML-unsafe (tainted)";
      if (TaintTracer::IsTraceEnabled(TAINT_BIT_TRACE_HTML)) {
        force_warning = true;
        aux = TaintTracer::ExtractTrace(td.getTaintTrace());
      }
      break;

    case TAINT_BIT_MUTATED:
      buf += "non-static (tainted)";
      break;

    case TAINT_BIT_SQL:
      buf += "SQL-unsafe (tainted)";
      break;

    case TAINT_BIT_SHELL:
      buf += "shell-unsafe (tainted)";
      break;

    case TAINT_BIT_ALL:
      buf += "tainted";
      break;

    default:
      return;
  }
  buf += " string!\n";

  if (RuntimeOption::EnableTaintWarnings || force_warning) {
    buf += aux;
    buf += "\n";

    buf += "---begin output---\n";
    buf += s.c_str();
    buf += "\n";
    buf += "----end output----\n";

    ZeroCount(bit);
    raise_warning(buf);
  } else {
    IncCount(bit);
  }
}
예제 #6
0
bool f_defined(CStrRef name, bool autoload /* = true */) {
  if (!name.get()) return false;
  const char *data = name.data();
  int len = name.length();
  char *colon;
  if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
    // class constant
    int classNameLen = colon - data;
    char *constantName = colon + 2;
    VM::Class* cls = getClassByName(data, classNameLen);
    if (cls) {
      String cnsName(constantName, data + len - constantName, CopyString);
      return cls->clsCnsGet(cnsName.get());
    }
    return false;
  } else {
    return autoload ?
      VM::Unit::loadCns(name.get()) :
      VM::Unit::lookupCns(name.get());
  }
}
예제 #7
0
CVarRef ZendArray::get(CStrRef k, bool error /* = false */) const {
  StringData *key = k.get();
  int64 prehash = key->hash();
  Bucket *p = find(key->data(), key->size(), prehash);
  if (p) {
    return p->data;
  }
  if (error) {
    raise_notice("Undefined index: %s", k.data());
  }
  return null_variant;
}
예제 #8
0
Variant f_constant(CStrRef name) {
  if (!name.get()) return uninit_null();
  const char *data = name.data();
  int len = name.length();

  // slice off starting backslash
  bool hadInitialBackslash = false;
  if (len > 0 && data[0] == '\\') {
    data += 1;
    len -= 1;
    hadInitialBackslash = true;
  }

  char *colon;
  if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
    // class constant
    int classNameLen = colon - data;
    char *constantName = colon + 2;
    Class* cls = getClassByName(data, classNameLen);
    if (cls) {
      String cnsName(constantName, data + len - constantName, CopyString);
      TypedValue* tv = cls->clsCnsGet(cnsName.get());
      if (tv) {
        return tvAsCVarRef(tv);
      }
    }
    raise_warning("Couldn't find constant %s", data);
  } else {
    TypedValue* cns;
    if (hadInitialBackslash) {
      String s(data, len, CopyString);
      cns = Unit::loadCns(s.get());
    } else {
      cns = Unit::loadCns(name.get());
    }
    if (cns) return tvAsVariant(cns);
  }

  return uninit_null();
}
예제 #9
0
void f_hphp_set_static_property(CStrRef cls, CStrRef prop, CVarRef value) {
  StringData* sd = cls.get();
  Class* class_ = Unit::lookupClass(sd);
  if (class_ == nullptr) {
    String normName = normalizeNS(sd);
    if (normName) {
      return f_hphp_set_static_property(normName, prop, value);
    } else {
      raise_error("Non-existent class %s", sd->data());
    }
  }
  VMRegAnchor _;
  bool visible, accessible;
  TypedValue* tv = class_->getSProp(arGetContextClass(
                                      g_vmContext->getFP()),
                                    prop.get(), visible, accessible);
  if (tv == nullptr) {
    raise_error("Class %s does not have a property named %s",
                cls.get()->data(), prop.get()->data());
  }
  if (!visible || !accessible) {
    raise_error("Invalid access to class %s's property %s",
                cls.get()->data(), prop.get()->data());
  }
  tvAsVariant(tv) = value;
}
예제 #10
0
Array f_hphp_get_function_info(CStrRef name) {
  Array ret;
  const Func* func = Unit::loadFunc(name.get());
  if (!func) return ret;
  ret.set(s_name,       VarNR(func->name()));
  ret.set(s_closure,    empty_string);

  // setting parameters and static variables
  set_function_info(ret, func);
  set_source_info(ret, func->unit()->filepath()->data(),
                  func->line1(), func->line2());
  return ret;
}
예제 #11
0
Array vm_get_class_vars(CStrRef className) {
  HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get());
  if (cls == NULL) {
    raise_error("Unknown class %s", className->data());
  }
  cls->initialize();

  const VM::Class::SProp* sPropInfo = cls->staticProperties();
  const size_t numSProps = cls->numStaticProperties();
  const VM::Class::Prop* propInfo = cls->declProperties();
  const size_t numDeclProps = cls->numDeclProperties();

  // The class' instance property initialization template is in different
  // places, depending on whether it has any request-dependent initializers
  // (i.e. constants)
  const VM::Class::PropInitVec& declPropInitVec = cls->declPropInit();
  const VM::Class::PropInitVec* propVals = !cls->pinitVec().empty()
    ? cls->getPropData() : &declPropInitVec;
  ASSERT(propVals != NULL);
  ASSERT(propVals->size() == numDeclProps);

  // For visibility checks
  CallerFrame cf;
  HPHP::VM::Class* ctx = arGetContextClass(cf());
  const ClassInfo* ctxCI =
    (ctx == NULL ? NULL : g_vmContext->findClassInfo(CStrRef(ctx->nameRef())));
  ClassInfo::PropertyMap propMap;
  g_vmContext->findClassInfo(className)->getAllProperties(propMap);

  HphpArray* ret = NEW(HphpArray)(numDeclProps + numSProps);

  for (size_t i = 0; i < numDeclProps; ++i) {
    StringData* name = const_cast<StringData*>(propInfo[i].m_name);
    // Empty names are used for invisible/private parent properties; skip them
    if (name->size() == 0) continue;
    if (propMap[String(name)]->isVisible(ctxCI)) {
      const TypedValue* value = &((*propVals)[i]);
      ret->nvSet(name, value, false);
    }
  }

  for (size_t i = 0; i < numSProps; ++i) {
    bool vis, access;
    TypedValue* value = cls->getSProp(ctx, sPropInfo[i].m_name, vis, access);
    if (vis) {
      ret->nvSet(const_cast<StringData*>(sPropInfo[i].m_name), value, false);
    }
  }

  return ret;
}
예제 #12
0
void VariableSerializer::write(CStrRef v) {
  if (m_type == APCSerialize && !v.isNull() && v->isStatic()) {
    union {
      char buf[8];
      StringData *sd;
    } u;
    u.sd = v.get();
    m_buf->append("S:");
    m_buf->append(u.buf, 8);
    m_buf->append(';');
  } else {
    v.serialize(this);
  }
}
예제 #13
0
파일: eval.cpp 프로젝트: sclin/hiphop-php
bool eval_invoke_file_hook(Variant &res, CStrRef path, bool once,
                           LVariableTable* variables, const char *currentDir) {
  bool initial;
  HPHP::Eval::PhpFile* efile =
    g_vmContext->lookupPhpFile(path.get(), currentDir, &initial);
  HPHP::VM::Unit* u = nullptr;
  if (efile) u = efile->unit();
  if (u == nullptr) {
    return false;
  }
  if (!once || initial) {
    g_vmContext->invokeUnit((TypedValue*)(&res), u);
  }
  return true;
}
예제 #14
0
bool f_define(CStrRef name, CVarRef value,
              bool case_insensitive /* = false */) {
  if (case_insensitive) {
    raise_warning(Strings::CONSTANTS_CASE_SENSITIVE);
  }
  if (hhvm) {
    // TODO: Once we're inlining constants from hphpc this should
    // fatal or fail in some other way.
    return g_vmContext->setCns(name.get(), value, true);
  } else {
    // define() should be turned into constant definition by HPHP
    assert(false);
    return false;
  }
}
예제 #15
0
Array f_get_class_constants(CStrRef class_name) {
  if (hhvm) {
    return vm_get_class_constants(class_name.get());
  }
  const ClassInfo *cls = ClassInfo::FindClass(class_name);
  Array ret = Array::Create();
  if (cls) {
    const ClassInfo::ConstantVec &constants = cls->getConstantsVec();
    for (ClassInfo::ConstantVec::const_iterator iter = constants.begin();
         iter != constants.end(); ++iter) {
      ret.set((*iter)->name, (*iter)->getValue());
    }
  }
  return ret;
}
예제 #16
0
static bool is_a_impl(CVarRef class_or_object, CStrRef class_name,
                      bool allow_string, bool subclass_only) {
    if (class_or_object.isString() && !allow_string) {
        return false;
    }

    const Class* cls = get_cls(class_or_object);
    if (!cls) return false;
    if (cls->attrs() & AttrTrait) return false;
    const Class* other = lookup_class(class_name.get());
    if (!other) return false;
    if (other->attrs() & AttrTrait) return false;
    if (other == cls) return !subclass_only;
    return cls->classof(other);
}
예제 #17
0
bool f_trait_exists(CStrRef trait_name, bool autoload /* = true */) {
  if (hhvm) {
    return VM::Unit::classExists(trait_name.get(), autoload, VM::AttrTrait);
  }
  const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(trait_name);

  if (info) {
    return info->getAttribute() & ClassInfo::IsTrait;
  }

  if (!autoload) return false;

  AutoloadHandler::s_instance->invokeHandler(trait_name);
  return f_trait_exists(trait_name, false);
}
예제 #18
0
Variant f_get_class_vars(CStrRef className) {
    const Class* cls = Unit::loadClass(className.get());
    if (!cls) {
        return false;
    }
    cls->initialize();

    const Class::SProp* sPropInfo = cls->staticProperties();
    const size_t numSProps = cls->numStaticProperties();
    const Class::Prop* propInfo = cls->declProperties();
    const size_t numDeclProps = cls->numDeclProperties();

    // The class' instance property initialization template is in different
    // places, depending on whether it has any request-dependent initializers
    // (i.e. constants)
    const Class::PropInitVec& declPropInitVec = cls->declPropInit();
    const Class::PropInitVec* propVals = !cls->pinitVec().empty()
                                         ? cls->getPropData() : &declPropInitVec;
    assert(propVals != NULL);
    assert(propVals->size() == numDeclProps);

    // For visibility checks
    CallerFrame cf;
    Class* ctx = arGetContextClass(cf());

    ArrayInit arr(numDeclProps + numSProps);

    for (size_t i = 0; i < numDeclProps; ++i) {
        StringData* name = const_cast<StringData*>(propInfo[i].m_name);
        // Empty names are used for invisible/private parent properties; skip them
        assert(name->size() != 0);
        if (Class::IsPropAccessible(propInfo[i], ctx)) {
            const TypedValue* value = &((*propVals)[i]);
            arr.set(name, tvAsCVarRef(value), true /* isKey */);
        }
    }

    for (size_t i = 0; i < numSProps; ++i) {
        bool vis, access;
        TypedValue* value = cls->getSProp(ctx, sPropInfo[i].m_name, vis, access);
        if (access) {
            arr.set(const_cast<StringData*>(sPropInfo[i].m_name),
                    tvAsCVarRef(value), true /* isKey */);
        }
    }

    return arr.toArray();
}
예제 #19
0
bool f_class_exists(CStrRef class_name, bool autoload /* = true */) {
  if (hhvm) {
    return VM::Unit::classExists(class_name.get(), autoload, VM::AttrNone);
  }
  const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(class_name);

  if (info) {
    ClassInfo::Attribute attr = info->getAttribute();
    return !(attr & (ClassInfo::IsInterface|ClassInfo::IsTrait));
  }

  if (!autoload) return false;

  AutoloadHandler::s_instance->invokeHandler(class_name);
  return f_class_exists(class_name, false);
}
예제 #20
0
/**
 * The Map::accessor here establishes a write lock, which means that other
 * threads, protected by read locks through Map::const_accessor, will not
 * read erased values from APC.
 * The ReadLock here is to sync with clear(), which only has a WriteLock,
 * not a specific accessor.
 */
bool ConcurrentTableSharedStore::eraseImpl(CStrRef key, bool expired) {
  if (key.isNull()) return false;
  ReadLock l(m_lock);
  Map::accessor acc;
  if (m_vars.find(acc, key.data())) {
    if (expired && !acc->second.expired()) {
      return false;
    }
    if (RuntimeOption::EnableAPCSizeStats) {
      SharedStoreStats::removeDirect(key.size(), acc->second.size);
      if (RuntimeOption::EnableAPCSizeGroup) {
        SharedStoreStats::onDelete(key.get(), acc->second.var, false);
      }
    }
    eraseAcc(acc);
    return true;
  }
  return false;
}
예제 #21
0
bool eval_invoke_file_hook(Variant &res, CStrRef path, bool once,
                           LVariableTable* variables, const char *currentDir) {
  if (hhvm) {
    bool initial;
    HPHP::Eval::PhpFile* efile =
      g_vmContext->lookupPhpFile(path.get(), currentDir, &initial);
    HPHP::VM::Unit* u = NULL;
    if (efile) u = efile->unit();
    if (u == NULL) {
      return false;
    }
    if (!once || initial) {
      g_vmContext->invokeUnit((TypedValue*)(&res), u);
    }
    return true;
  } else {
    return RequestEvalState::includeFile(res, path, once, variables,
                                         currentDir);
  }
}
예제 #22
0
Array vm_get_class_constants(CStrRef className) {
  HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get());
  if (cls == NULL) {
    return NEW(HphpArray)(0);
  }

  size_t numConstants = cls->numConstants();
  HphpArray* retVal = NEW(HphpArray)(numConstants);
  const VM::Class::Const* consts = cls->constants();
  for (size_t i = 0; i < numConstants; i++) {
    // Note: hphpc doesn't include inherited constants in
    // get_class_constants(), so mimic that behavior
    if (consts[i].m_class == cls) {
      StringData* name  = const_cast<StringData*>(consts[i].m_name);
      TypedValue* value = cls->clsCnsGet(consts[i].m_name);
      retVal->nvSet(name, value, false);
    }
  }

  return retVal;
}
예제 #23
0
Variant f_get_called_class() {
  if (hhvm) {
    CallerFrame cf;
    ActRec* ar = cf();
    if (ar == NULL) {
      return Variant(false);
    }
    if (ar->hasThis()) {
      ObjectData* obj = ar->getThis();
      return obj->o_getClassName();
    } else if (ar->hasClass()) {
      return ar->getClass()->preClass()->name()->data();
    } else {
      return Variant(false);
    }
  } else {
    CStrRef cls = FrameInjection::GetStaticClassName(
      ThreadInfo::s_threadInfo.getNoCheck());
    return cls.size() ? Variant(cls.get()) : Variant(false);
  }
}
예제 #24
0
bool ConcurrentTableSharedStore::exists(CStrRef key) {
 bool stats = RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats;
 bool statsFetch = RuntimeOption::EnableAPCSizeStats &&
                   RuntimeOption::EnableAPCFetchStats;
 const StoreValue *val;
 ReadLock l(m_lock);
 bool expired = false;
 {
   Map::const_accessor acc;
   if (!m_vars.find(acc, key.data())) {
     if (stats) ServerStats::Log("apc.miss", 1);
     return false;
   } else {
     val = &acc->second;
     if (val->expired()) {
       // Because it only has a read lock on the data, deletion from
       // expiration has to happen after the lock is released
       expired = true;
     } else {
       // No need toLocal() here, avoiding the copy
       if (statsFetch) {
         SharedStoreStats::onGet(key.get(), val->var);
       }
     }
   }
 }
 if (expired) {
   if (stats) {
     ServerStats::Log("apc.miss", 1);
   }
   eraseImpl(key, true);
   return false;
 }
 if (stats) {
   ServerStats::Log("apc.hit", 1);
 }
 return true;
}
예제 #25
0
파일: ext_spl.cpp 프로젝트: inez/hiphop-php
static int64 hphp_get_call_info_and_extra(
    CStrRef cls, CStrRef func, int64 &extra) {
  if (func.empty()) {
    throw_spl_exception("Invalid function name given");
  }

  if (cls.empty()) {
    const CallInfo *cit;
    void *extrap;
    get_call_info_or_fail(cit, extrap, func);
    extra = (int64) extrap;
    return (int64) cit;
  } else {
    MethodCallPackage mcp;
    mcp.rootCls = cls.get();
    mcp.name = &func;
    if (!get_call_info_static_method(mcp)) {
      throw_spl_exception("Could not find method %s for class %s",
                          func.c_str(), cls.c_str());
    }
    extra = (int64) mcp.extra;
    return (int64) mcp.ci;
  }
}
예제 #26
0
DebuggerProxyPtr Debugger::GetProxy() {
  TRACE(2, "Debugger::GetProxy\n");
  CStrRef sandboxId = g_context->getSandboxId();
  return s_debugger.findProxy(sandboxId.get());
}
예제 #27
0
void Debugger::UnregisterSandbox(CStrRef id) {
  TRACE(2, "Debugger::UnregisterSandbox\n");
  s_debugger.unregisterSandbox(id.get());
}
예제 #28
0
void rename_function(CStrRef old_name, CStrRef new_name) {
  g_vmContext->renameFunction(old_name.get(), new_name.get());
}
예제 #29
0
bool check_renamed_function(CStrRef name) {
  return g_vmContext->isFunctionRenameable(name.get());
}
예제 #30
0
StringName::StringName(CONSTRUCT_ARGS, CStrRef name, bool isSp /* = false */)
  : Name(CONSTRUCT_PASS),
  m_name(name.get()), m_isSp(isSp), m_sg(VariableIndex::isSuperGlobal(m_name)) {
  ASSERT(m_name->isStatic());
}