예제 #1
0
bool ArrayData::hasInternalReference(PointerSet &vars,
                                     bool ds /* = false */) const {
  if (isSharedMap()) return false;
  for (ArrayIter iter(this); iter; ++iter) {
    CVarRef var = iter.secondRef();
    if (var.isReferenced()) {
      Variant *pvar = var.getRefData();
      if (vars.find(pvar) != vars.end()) {
        return true;
      }
      vars.insert(pvar);
    }
    if (var.isObject()) {
      ObjectData *pobj = var.getObjectData();
      if (vars.find(pobj) != vars.end()) {
        return true;
      }
      vars.insert(pobj);
      if (ds && pobj->o_instanceof("Serializable")) {
        return true;
      }
      if (pobj->hasInternalReference(vars, ds)) {
        return true;
      }
    } else if (var.isArray() &&
               var.getArrayData()->hasInternalReference(vars, ds)) {
      return true;
    }
  }
  return false;
}
예제 #2
0
ObjectData *FuncScopeVariableEnvironment::getContinuation() const {
  const vector<ParameterPtr> &params = m_func->getParams();
  if (m_func->name().find('0') == 0 && params.size() == 1
   && params[0]->getName().find(CONTINUATION_OBJECT_NAME) == 0) {
    Array args = getParams();
    ASSERT(args.size() == 1);
    ObjectData *obj = args[0].getObjectData();
    if (obj->o_instanceof("Continuation")) return obj;
  }
  return NULL;
}
예제 #3
0
SharedVariant* SharedVariant::convertObj(CVarRef var) {
  if (!var.is(KindOfObject) || getObjAttempted()) {
    return NULL;
  }
  setObjAttempted();
  PointerSet seen;
  ObjectData *obj = var.getObjectData();
  if (obj->o_instanceof("Serializable")) {
    // should also check the object itself
    return NULL;
  }
  if (obj->hasInternalReference(seen, true)) {
    return NULL;
  }
  SharedVariant *tmp = new SharedVariant(var, false, true, true);
  tmp->setObjAttempted();
  return tmp;
}
예제 #4
0
bool ArrayData::hasInternalReference(PointerSet &vars,
                                     bool ds /* = false */) const {
    if (isSharedMap()) return false;
    for (ArrayIter iter(this); iter; ++iter) {
        CVarRef var = iter.secondRef();
        if (var.isReferenced()) {
            Variant *pvar = var.getVariantData();
            if (vars.find(pvar) != vars.end()) {
                return true;
            }
            vars.insert(pvar);
        }
        if (var.isObject()) {
            ObjectData *pobj = var.getObjectData();
            if (vars.find(pobj) != vars.end()) {
                return true;
            }
            vars.insert(pobj);
            if (pobj->o_instanceof("Serializable")) {
                if (ds) {
                    // We want to detect Serializable object as well
                    return true;
                } else {
                    // Serializable object does not have internal reference issue
                    return false;
                }
            }
            if (pobj->o_toArray().get()->hasInternalReference(vars, ds)) {
                return true;
            }
        } else if (var.isArray() &&
                   var.getArrayData()->hasInternalReference(vars, ds)) {
            return true;
        }
    }
    return false;
}
예제 #5
0
bool f_is_callable(CVarRef v, bool syntax /* = false */,
                   VRefParam name /* = null */) {
  bool ret = true;
  if (LIKELY(!syntax)) {
    if (hhvm) {
      CallerFrame cf;
      ObjectData* obj = NULL;
      HPHP::VM::Class* cls = NULL;
      StringData* invName = NULL;
      const HPHP::VM::Func* f = vm_decode_function(v, cf(), false, obj, cls,
                                                   invName, false);
      if (f == NULL) {
        ret = false;
      }
      if (invName != NULL) {
        LITSTR_DECREF(invName);
      }
    } else {
      MethodCallPackage mcp;
      String classname, methodname;
      bool doBind;
      ret = get_user_func_handler(v, true, mcp,
                                  classname, methodname, doBind, false);
      if (ret && mcp.ci->m_flags & (CallInfo::Protected|CallInfo::Private)) {
        classname = mcp.getClassName();
        if (!ClassInfo::HasAccess(classname, *mcp.name,
                                  mcp.ci->m_flags & CallInfo::StaticMethod ||
                                  !mcp.obj,
                                  mcp.obj)) {
          ret = false;
        }
      }
    }
    if (!name.isReferenced()) return ret;
  }

  Variant::TypedValueAccessor tv_func = v.getTypedAccessor();
  if (Variant::IsString(tv_func)) {
    if (name.isReferenced()) name = Variant::GetStringData(tv_func);
    return ret;
  }

  if (Variant::GetAccessorType(tv_func) == KindOfArray) {
    CArrRef arr = Variant::GetAsArray(tv_func);
    CVarRef clsname = arr.rvalAtRef(0LL);
    CVarRef mthname = arr.rvalAtRef(1LL);
    if (arr.size() != 2 ||
        &clsname == &null_variant ||
        &mthname == &null_variant) {
      name = v.toString();
      return false;
    }

    Variant::TypedValueAccessor tv_meth = mthname.getTypedAccessor();
    if (!Variant::IsString(tv_meth)) {
      if (name.isReferenced()) name = v.toString();
      return false;
    }

    Variant::TypedValueAccessor tv_cls = clsname.getTypedAccessor();
    if (Variant::GetAccessorType(tv_cls) == KindOfObject) {
      name = Variant::GetObjectData(tv_cls)->o_getClassName();
    } else if (Variant::IsString(tv_cls)) {
      name = Variant::GetStringData(tv_cls);
    } else {
      name = v.toString();
      return false;
    }

    name = concat3(name, "::", Variant::GetAsString(tv_meth));
    return ret;
  }

  if (Variant::GetAccessorType(tv_func) == KindOfObject) {
    ObjectData *d = Variant::GetObjectData(tv_func);
    if (hhvm) {
      static const StringData* sd__invoke
        = StringData::GetStaticString("__invoke");
      const VM::Func* invoke = d->getVMClass()->lookupMethod(sd__invoke);
      if (name.isReferenced()) {
        if (d->o_instanceof("closure")) {
          // Hack to stop the mangled name from showing up
          name = "Closure::__invoke";
        } else {
          name = d->o_getClassName() + "::__invoke";
        }
      }
      return invoke != NULL;
    } else {
      void *extra;
      if (d->t___invokeCallInfoHelper(extra)) {
        name = d->o_getClassName() + "::__invoke";
        return ret;
      }
      if (name.isReferenced()) {
        name = v.toString();
      }
    }
  }

  return false;
}