Esempio n. 1
0
File: type.cpp Progetto: StetHD/hhvm
// Return true if the array satisfies requirement on the ArraySpec.
static bool arrayFitsSpec(const ArrayData* arr, const ArraySpec spec) {
  if (spec == ArraySpec::Top) return true;

  if (auto const spec_kind = spec.kind()) {
    if (arr->kind() == spec_kind) return true;
  }

  if (auto const rat_type = spec.type()) {
    using A = RepoAuthType::Array;
    if (arr->empty() && rat_type->emptiness() != A::Empty::No) return true;
    if (arr->isVectorData()) {
      switch (rat_type->tag()) {
        case A::Tag::Packed:
          if (arr->size() != rat_type->size()) break;
          // fall through
        case A::Tag::PackedN: {
          int64_t k = 0;
          for ( ; k < arr->size(); ++k) {
            auto const specElemType =
              rat_type->tag() == A::Tag::Packed ? rat_type->packedElem(k)
                                                : rat_type->elemType();
            if (!tvMatchesRepoAuthType(*(arr->get(k).asTypedValue()),
                                       specElemType)) {
              break;
            }
          }
          if (k == arr->size()) return true;
          break;
        }
      }
    }
  }

  return false;
}
Esempio n. 2
0
static void unserializeProp(VariableUnserializer* uns,
                            ObjectData* obj,
                            const String& key,
                            Class* ctx,
                            const String& realKey,
                            int nProp) {
  // Do a two-step look up
  auto const lookup = obj->getProp(ctx, key.get());
  Variant* t;

  if (!lookup.prop || !lookup.accessible) {
    // Dynamic property. If this is the first, and we're using MixedArray,
    // we need to pre-allocate space in the array to ensure the elements
    // dont move during unserialization.
    //
    // TODO(#2881866): this assumption means we can't do reallocations
    // when promoting kPackedKind -> kMixedKind.
    t = &obj->reserveProperties(nProp).lvalAt(realKey, AccessFlags::Key);
  } else {
    t = &tvAsVariant(lookup.prop);
  }

  if (UNLIKELY(IS_REFCOUNTED_TYPE(t->getRawType()))) {
    uns->putInOverwrittenList(*t);
  }

  unserializeVariant(*t, uns);
  if (!RuntimeOption::RepoAuthoritative) return;
  if (!Repo::get().global().HardPrivatePropInference) return;

  /*
   * We assume for performance reasons in repo authoriative mode that
   * we can see all the sets to private properties in a class.
   *
   * It's a hole in this if we don't check unserialization doesn't
   * violate what we've seen, which we handle by throwing if the repo
   * was built with this option.
   */
  auto const cls  = obj->getVMClass();
  auto const slot = cls->lookupDeclProp(key.get());
  if (UNLIKELY(slot == kInvalidSlot)) return;
  auto const repoTy = obj->getVMClass()->declPropRepoAuthType(slot);
  if (LIKELY(tvMatchesRepoAuthType(*t->asTypedValue(), repoTy))) {
    return;
  }

  auto msg = folly::format(
    "Property {} for class {} was deserialized with type ({}) that "
    "didn't match what we inferred in static analysis",
    key.data(),
    obj->getVMClass()->name()->data(),
    tname(t->asTypedValue()->m_type)
  ).str();
  throw Exception(msg);
}