Ejemplo n.º 1
0
bool TestExtVariable::test_unserialize() {
  {
    // this was crashing
    unserialize_from_string(StringUtil::HexDecode("53203a20224c612072756f74612067697261207065722074757474692220204d203a20227365636f6e646f206d6520736920c3a820696e6361737472617461206461207175616c6368652070617274652122"));
  }
  {
    Variant v = unserialize_from_string("O:8:\"stdClass\":1:{s:4:\"name\";s:5:\"value\";}");
    VERIFY(v.is(KindOfObject));
    Object obj = v.toObject();
    VS(obj->o_getClassName(), "stdClass");
    VS(obj.o_get("name"), "value");
  }
  {
    Variant v = unserialize_from_string(String("O:8:\"stdClass\":1:{s:7:\"\0*\0name\";s:5:\"value\";}", 45, AttachLiteral));
    VERIFY(v.is(KindOfObject));
    Object obj = v.toObject();
    VS(obj->o_getClassName(), "stdClass");
    VS(obj.o_get("name"), uninit_null());
  }
  {
    Variant v1 = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3));
    Variant v2 = unserialize_from_string("a:3:{s:1:\"a\";s:5:\"apple\";s:1:\"b\";i:2;s:1:\"c\";a:3:{i:0;i:1;i:1;s:1:\"y\";i:2;i:3;}}");
    VS(v1, v2);
  }
  return Count(true);
}
Ejemplo n.º 2
0
void objectToBSON(const Object& value, const char* key, bson_t* bson) {
  const String& className = value->o_getClassName();

  if (className == s_MongoId) {
    mongoIdToBSON(value, key, bson);
  } else if (className == s_MongoDate) {
    mongoDateToBSON(value, key, bson);
  } else if (className == s_MongoRegex) {
    mongoRegexToBSON(value, key, bson);
  } else if (className == s_MongoTimestamp) {
    mongoTimestampToBSON(value, key, bson);
  } else if (className == s_MongoCode) {
    mongoCodeToBSON(value, key, bson);
  } else if (className == s_MongoBinData) {
    mongoBinDataToBSON(value, key, bson);
  } else if (className == s_MongoInt32) {
    mongoInt32ToBSON(value, key, bson);
  } else if (className == s_MongoInt64) {
    mongoInt64ToBSON(value, key, bson);
  } else if (className == s_MongoMaxKey) {
    mongoMaxKeyToBSON(key, bson);
  } else if (className == s_MongoMinKey) {
    mongoMinKeyToBSON(key, bson);
  } else {
    arrayToBSON(value.toArray(), key, bson);
  }
}
Ejemplo n.º 3
0
void CmdInterrupt::sendImpl(DebuggerThriftBuffer &thrift) {
  DebuggerCommand::sendImpl(thrift);
  thrift.write(m_interrupt);
  thrift.write(m_program);
  thrift.write(m_errorMsg);
  thrift.write(m_threadId);
  thrift.write(m_pendingJump);
  if (m_site) {
    thrift.write(true);
    thrift.write(m_site->getFile());
    thrift.write(m_site->getLine0());
    thrift.write(m_site->getChar0());
    thrift.write(m_site->getLine1());
    thrift.write(m_site->getChar1());
    thrift.write(m_site->getNamespace());
    thrift.write(m_site->getClass());
    thrift.write(m_site->getFunction());
    Object e = m_site->getException();
    if (e.isNull()) {
      thrift.write("");
    } else {
      thrift.write(e->o_getClassName());
    }
    thrift.write(DebuggerClient::FormatVariable(e));
  } else {
    thrift.write(false);
  }
  BreakPointInfo::SendImpl(m_matched, thrift);
}
Ejemplo n.º 4
0
bool TestExtVariable::test_unserialize() {
  {
    Variant v = f_unserialize("O:8:\"stdClass\":1:{s:4:\"name\";s:5:\"value\";}");
    VERIFY(v.is(KindOfObject));
    Object obj = v.toObject();
    VS(obj->o_getClassName(), "stdClass");
    VS(obj.o_get("name"), "value");
  }
  {
    Variant v = f_unserialize(String("O:8:\"stdClass\":1:{s:7:\"\0*\0name\";s:5:\"value\";}", 45, AttachLiteral));
    VERIFY(v.is(KindOfObject));
    Object obj = v.toObject();
    VS(obj->o_getClassName(), "stdClass");
    VS(obj.o_get("name"), "value");
  }
  {
    Variant v1 = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3));
    Variant v2 = f_unserialize("a:3:{s:1:\"a\";s:5:\"apple\";s:1:\"b\";i:2;s:1:\"c\";a:3:{i:0;i:1;i:1;s:1:\"y\";i:2;i:3;}}");
    VS(v1, v2);
  }
  return Count(true);
}
Ejemplo n.º 5
0
void Variant::unserialize(VariableUnserializer *uns,
                          Uns::Mode mode /* = Uns::Mode::Value */) {

  // NOTE: If you make changes to how serialization and unserialization work,
  // make sure to update the reserialize() method in "runtime/ext/ext_apc.cpp"
  // and to update test_apc_reserialize() in "test/ext/test_ext_apc.cpp".

  char type, sep;
  type = uns->readChar();
  sep = uns->readChar();

  if (type != 'R') {
    uns->add(this, mode);
  }

  if (type == 'N') {
    if (sep != ';') throw Exception("Expected ';' but got '%c'", sep);
    setNull(); // NULL *IS* the value, without we get undefined warnings
    return;
  }
  if (sep != ':') {
    throw Exception("Expected ':' but got '%c'", sep);
  }

  switch (type) {
  case 'r':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByVal(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      operator=(*v);
    }
    break;
  case 'R':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByRef(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      assignRef(*v);
    }
    break;
  case 'b': { int64_t v = uns->readInt(); operator=((bool)v); } break;
  case 'i': { int64_t v = uns->readInt(); operator=(v);       } break;
  case 'd':
    {
      double v;
      char ch = uns->peek();
      bool negative = false;
      char buf[4];
      if (ch == '-') {
        negative = true;
        ch = uns->readChar();
        ch = uns->peek();
      }
      if (ch == 'I') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "INF")) {
          throw Exception("Expected 'INF' but got '%s'", buf);
        }
        v = atof("inf");
      } else if (ch == 'N') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "NAN")) {
          throw Exception("Expected 'NAN' but got '%s'", buf);
        }
        v = atof("nan");
      } else {
        v = uns->readDouble();
      }
      operator=(negative ? -v : v);
    }
    break;
  case 's':
    {
      String v;
      v.unserialize(uns);
      operator=(v);
    }
    break;
  case 'S':
    if (uns->getType() == VariableUnserializer::Type::APCSerialize) {
      union {
        char buf[8];
        StringData *sd;
      } u;
      uns->read(u.buf, 8);
      operator=(u.sd);
    } else {
      throw Exception("Unknown type '%c'", type);
    }
    break;
  case 'a':
    {
      Array v = Array::Create();
      v.unserialize(uns);
      operator=(v);
      return; // array has '}' terminating
    }
    break;
  case 'L':
    {
      int64_t id = uns->readInt();
      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      String rsrcName;
      rsrcName.unserialize(uns);
      sep = uns->readChar();
      if (sep != '{') {
        throw Exception("Expected '{' but got '%c'", sep);
      }
      sep = uns->readChar();
      if (sep != '}') {
        throw Exception("Expected '}' but got '%c'", sep);
      }
      DummyResource* rsrc = NEWOBJ(DummyResource);
      rsrc->o_setResourceId(id);
      rsrc->m_class_name = rsrcName;
      operator=(rsrc);
      return; // resource has '}' terminating
    }
    break;
  case 'O':
  case 'V':
  case 'K':
    {
      String clsName;
      clsName.unserialize(uns);

      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      int64_t size = uns->readInt();
      char sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      sep = uns->readChar();
      if (sep != '{') {
        throw Exception("Expected '{' but got '%c'", sep);
      }

      const bool allowObjectFormatForCollections = true;

      Class* cls;
      // If we are potentially dealing with a collection, we need to try to
      // load the collection class under an alternate name so that we can
      // deserialize data that was serialized before the migration of
      // collections to the HH namespace.

      if (type != 'O') {
        // Collections are CPP builtins; don't attempt to autoload
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
      } else if (allowObjectFormatForCollections) {
        // In order to support the legacy {O|V}:{Set|Vector|Map}
        // serialization, we defer autoloading until we know that there's
        // no alternate (builtin) collection class.
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
        if (!cls) {
          cls = Unit::loadClass(clsName.get()); // with autoloading
        }
      } else {
        cls = Unit::loadClass(clsName.get()); // with autoloading
      }

      Object obj;
      if (RuntimeOption::UnserializationWhitelistCheck &&
          (type == 'O') &&
          !uns->isWhitelistedClass(clsName)) {
        const char* err_msg =
          "The object being unserialized with class name '%s' "
          "is not in the given whitelist. "
          "See http://fburl.com/SafeSerializable for more detail";
        if (RuntimeOption::UnserializationWhitelistCheckWarningOnly) {
          raise_warning(err_msg, clsName.c_str());
        } else {
          raise_error(err_msg, clsName.c_str());
        }
      }
      if (cls) {
        // Only unserialize CPP extension types which can actually
        // support it. Otherwise, we risk creating a CPP object
        // without having it initialized completely.
        if (cls->instanceCtor() && !cls->isCppSerializable()) {
          obj = ObjectData::newInstance(
            SystemLib::s___PHP_Unserializable_ClassClass);
          obj->o_set(s_PHP_Unserializable_Class_Name, clsName);
        } else {
          obj = ObjectData::newInstance(cls);
          if (UNLIKELY(cls == c_Pair::classof() && size != 2)) {
            throw Exception("Pair objects must have exactly 2 elements");
          }
        }
      } else {
        obj = ObjectData::newInstance(
          SystemLib::s___PHP_Incomplete_ClassClass);
        obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
      }
      operator=(obj);

      if (size > 0) {
        if (type == 'O') {
          // Collections are not allowed
          if (obj->isCollection()) {
            if (size > 0) {
              throw Exception("%s does not support the 'O' serialization "
                              "format", clsName.data());
            }
            // Be lax and tolerate the 'O' serialization format for collection
            // classes if there are 0 properties.
            raise_warning("%s does not support the 'O' serialization "
                          "format", clsName.data());
          }
          /*
            Count backwards so that i is the number of properties
            remaining (to be used as an estimate for the total number
            of dynamic properties when we see the first dynamic prop).
            see getVariantPtr
          */
          for (int64_t i = size; i--; ) {
            String key = uns->unserializeKey().toString();
            int ksize = key.size();
            const char *kdata = key.data();
            int subLen = 0;
            if (kdata[0] == '\0') {
              if (UNLIKELY(!ksize)) {
                throw EmptyObjectPropertyException();
              }
              // private or protected
              subLen = strlen(kdata + 1) + 2;
              if (UNLIKELY(subLen >= ksize)) {
                if (subLen == ksize) {
                  throw EmptyObjectPropertyException();
                } else {
                  throw Exception("Mangled private object property");
                }
              }
              String k(kdata + subLen, ksize - subLen, CopyString);
              Class* ctx = (Class*)-1;
              if (kdata[1] != '*') {
                ctx = Unit::lookupClass(
                  String(kdata + 1, subLen - 2, CopyString).get());
              }
              unserializeProp(uns, obj.get(), k, ctx, key, i + 1);
            } else {
              unserializeProp(uns, obj.get(), key, nullptr, key, i + 1);
            }
          }
        } else {
          assert(type == 'V' || type == 'K');
          if (!obj->isCollection()) {
            throw Exception("%s is not a collection class", clsName.data());
          }
          collectionUnserialize(obj.get(), uns, size, type);
        }
      }
      sep = uns->readChar();
      if (sep != '}') {
        throw Exception("Expected '}' but got '%c'", sep);
      }

      obj->invokeWakeup();
      return; // object has '}' terminating
    }
    break;
  case 'C':
    {
      String clsName;
      clsName.unserialize(uns);

      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      String serialized;
      serialized.unserialize(uns, '{', '}');

      Object obj;
      try {
        obj = create_object_only(clsName);
      } catch (ClassNotFoundException &e) {
        if (!uns->allowUnknownSerializableClass()) {
          throw;
        }
        obj = create_object_only(s_PHP_Incomplete_Class);
        obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
        obj->o_set("serialized", serialized);
      }

      if (!obj->instanceof(SystemLib::s_SerializableClass)) {
        raise_warning("Class %s has no unserializer",
                      obj->o_getClassName().data());
      } else {
        obj->o_invoke_few_args(s_unserialize, 1, serialized);
        obj.get()->clearNoDestruct();
      }

      operator=(obj);
      return; // object has '}' terminating
    }
    break;
  default:
    throw Exception("Unknown type '%c'", type);
  }
  sep = uns->readChar();
  if (sep != ';') {
    throw Exception("Expected ';' but got '%c'", sep);
  }
}
Ejemplo n.º 6
0
bool WddxPacket::recursiveAddVar(const String& varName,
                                 const Variant& varVariant,
                                 bool hasVarTag) {

  bool isArray = varVariant.isArray();
  bool isObject = varVariant.isObject();

  if (isArray || isObject) {
    if (hasVarTag) {
      m_packetString += "<var name='";
      m_packetString += varName.data();
      m_packetString += "'>";
    }

    Array varAsArray;
    Object varAsObject = varVariant.toObject();
    if (isArray) varAsArray = varVariant.toArray();
    if (isObject) varAsArray = varAsObject.toArray();

    int length = varAsArray.length();
    if (length > 0) {
      ArrayIter it = ArrayIter(varAsArray);
      if (it.first().isString()) isObject = true;
      if (isObject) {
        m_packetString += "<struct>";
        if (!isArray) {
          m_packetString += "<var name='php_class_name'><string>";
          m_packetString += varAsObject->o_getClassName().c_str();
          m_packetString += "</string></var>";
        }
      } else {
        m_packetString += "<array length='";
        m_packetString += std::to_string(length);
        m_packetString += "'>";
      }
      for (ArrayIter it(varAsArray); it; ++it) {
        Variant key = it.first();
        Variant value = it.second();
        recursiveAddVar(key.toString(), value, isObject);
      }
      if (isObject) {
        m_packetString += "</struct>";
      }
      else {
        m_packetString += "</array>";
      }
    }
    else {
      //empty object
      if (isObject) {
        m_packetString += "<struct>";
        if (!isArray) {
          m_packetString += "<var name='php_class_name'><string>";
          m_packetString += varAsObject->o_getClassName().c_str();
          m_packetString += "</string></var>";
        }
        m_packetString += "</struct>";
      }
    }
    if (hasVarTag) {
      m_packetString += "</var>";
    }
    return true;
  }

  std::string varType = getDataTypeString(varVariant.getType()).data();
  if (!getWddxEncoded(varType, "", varName, false).empty()) {
    std::string varValue = varVariant.toString().data();
    if (varType.compare("boolean") == 0) {
      varValue = varVariant.toBoolean() ? "true" : "false";
    }
    m_packetString += getWddxEncoded(varType, varValue, varName, hasVarTag);
    return true;
  }

  return false;
}
Ejemplo n.º 7
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 str = v.toString();
    int c = str.find("::");
    if (c != 0 && c != String::npos && c + 2 < str.size()) {
      String classname = str.substr(0, c);
      String methodname = str.substr(c + 2);
      return f_class_exists(classname) &&
        ClassInfo::HasAccess(classname, methodname, true, false);
    }
    return f_function_exists(str);
  }

  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);
      Object obj;
      bool staticCall = false;
      if (v0.is(KindOfObject)) {
        obj = v0.toObject();
        v0 = obj->o_getClassName();
      } else if (v0.isString()) {
        if (!f_class_exists(v0.toString())) {
          return false;
        }
        staticCall = true;
      }
      if (v1.isString()) {
        String str = v1.toString();
        int c = str.find("::");
        if (c != 0 && c != String::npos && c + 2 < str.size()) {
          String name1 = v0.toString();
          String name2 = str.substr(0, c);
          ASSERT(name1.get() && name2.get());
          if (name1->isame(name2.get()) ||
              ClassInfo::IsSubClass(name1, name2, false)) {
            staticCall = true;
            v0 = name2;
            v1 = str.substr(c + 2);
          }
        }
      }
      if (v0.isString() && v1.isString()) {
        if (!name.isNull()) {
          name = v0.toString() + "::" + v1.toString();
        }
        if (same(v0, s_self) || same(v0, s_parent)) {
          throw NotImplementedException("augmenting class scope info");
        }
        return ClassInfo::HasAccess(v0, v1, staticCall, !obj.isNull());
      }
    }
  }

  if (!name.isNull()) {
    name = v.toString();
  }
  return false;
}
Ejemplo n.º 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);
      return f_call_user_func(2, "class_exists",
                              Array::Create(String(classname))) &&
        ClassInfo::hasAccess(classname, methodname, true, 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);
      Object obj;
      bool staticCall = false;
      if (v0.is(KindOfObject)) {
        obj = v0.toObject();
        v0 = obj->o_getClassName();
      } else if (v0.isString()) {
        if (!f_call_user_func(2, "class_exists",
                              Array::Create(v0))) {
          return false;
        }
        staticCall = true;
      }
      if (v1.isString()) {
        string lowered = Util::toLower((const char *)v1.toString());
        size_t c = lowered.find("::");
        if (c != 0 && c != string::npos && c+2 < lowered.size()) {
          string name1 = Util::toLower((const char *)v0.toString());
          string name2 = lowered.substr(0, c);
          if (name1 == name2 ||
              ClassInfo::isSubClass(name1, name2, false)) {
            staticCall = true;
            v0 = name2;
            v1 = lowered.substr(c+2);
          }
        }
      }
      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");
        }
        return ClassInfo::hasAccess(v0, v1, staticCall, !obj.isNull());
      }
    }
  }

  if (!name.isNull()) {
    name = v.toString();
  }
  return false;
}