/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "verifier_deps.h"

#include <cstring>
#include <sstream>

#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/indenter.h"
#include "base/leb128.h"
#include "base/mutex-inl.h"
#include "compiler_callbacks.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "oat/oat_file.h"
#include "obj_ptr-inl.h"
#include "reg_type.h"
#include "reg_type_cache-inl.h"
#include "runtime.h"

namespace art HIDDEN {
namespace verifier {

VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only)
    : output_only_(output_only) {
  for (const DexFile* dex_file : dex_files) {
    DCHECK(GetDexFileDeps(*dex_file) == nullptr);
    std::unique_ptr<DexFileDeps> deps(new DexFileDeps(dex_file->NumClassDefs()));
    dex_deps_.emplace(dex_file, std::move(deps));
  }
}

// Perform logical OR on two bit vectors and assign back to LHS, i.e. `to_update |= other`.
// Size of the two vectors must be equal.
// Size of `other` must be equal to size of `to_update`.
static inline void BitVectorOr(std::vector<bool>& to_update, const std::vector<bool>& other) {
  DCHECK_EQ(to_update.size(), other.size());
  std::transform(
      other.begin(), other.end(), to_update.begin(), to_update.begin(), std::logical_or<bool>());
}

void VerifierDeps::MergeWith(std::unique_ptr<VerifierDeps> other,
                             const std::vector<const DexFile*>& dex_files) {
  DCHECK(other != nullptr);
  DCHECK_EQ(dex_deps_.size(), other->dex_deps_.size());
  for (const DexFile* dex_file : dex_files) {
    DexFileDeps* my_deps = GetDexFileDeps(*dex_file);
    DexFileDeps& other_deps = *other->GetDexFileDeps(*dex_file);
    // We currently collect extra strings only on the main `VerifierDeps`,
    // which should be the one passed as `this` in this method.
    DCHECK(other_deps.strings_.empty());
    // Size is the number of class definitions in the dex file, and must be the
    // same between the two `VerifierDeps`.
    DCHECK_EQ(my_deps->assignable_types_.size(), other_deps.assignable_types_.size());
    for (uint32_t i = 0; i < my_deps->assignable_types_.size(); ++i) {
      my_deps->assignable_types_[i].merge(other_deps.assignable_types_[i]);
    }
    BitVectorOr(my_deps->verified_classes_, other_deps.verified_classes_);
  }
}

VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) {
  auto it = dex_deps_.find(&dex_file);
  return (it == dex_deps_.end()) ? nullptr : it->second.get();
}

const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) const {
  auto it = dex_deps_.find(&dex_file);
  return (it == dex_deps_.end()) ? nullptr : it->second.get();
}

dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
                                                          ObjPtr<mirror::Class> klass) {
  DCHECK(klass != nullptr);
  ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
  // Array and proxy classes do not have a dex cache.
  if (!klass->IsArrayClass() && !klass->IsProxyClass()) {
    DCHECK(dex_cache != nullptr) << klass->PrettyClass();
    if (dex_cache->GetDexFile() == &dex_file) {
      // FindStringId is slow, try to go through the class def if we have one.
      const dex::ClassDef* class_def = klass->GetClassDef();
      DCHECK(class_def != nullptr) << klass->PrettyClass();
      const dex::TypeId& type_id = dex_file.GetTypeId(class_def->class_idx_);
      if (kIsDebugBuild) {
        std::string temp;
        CHECK_EQ(GetIdFromString(dex_file, klass->GetDescriptor(&temp)), type_id.descriptor_idx_);
      }
      return type_id.descriptor_idx_;
    }
  }
  std::string temp;
  return GetIdFromString(dex_file, klass->GetDescriptor(&temp));
}

static inline VerifierDeps* GetMainVerifierDeps(VerifierDeps* local_deps) {
  // The main VerifierDeps is the one set in the compiler callbacks, which at the
  // end of verification will have all the per-thread VerifierDeps merged into it.
  CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
  if (callbacks == nullptr) {
    DCHECK(!Runtime::Current()->IsAotCompiler());
    return local_deps;
  }
  DCHECK(Runtime::Current()->IsAotCompiler());
  return callbacks->GetVerifierDeps();
}

static bool FindExistingStringId(const std::vector<std::string>& strings,
                                 const std::string& str,
                                 uint32_t* found_id) {
  uint32_t num_extra_ids = strings.size();
  for (size_t i = 0; i < num_extra_ids; ++i) {
    if (strings[i] == str) {
      *found_id = i;
      return true;
    }
  }
  return false;
}

dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
  const dex::StringId* string_id = dex_file.FindStringId(str.c_str());
  if (string_id != nullptr) {
    // String is in the DEX file. Return its ID.
    return dex_file.GetIndexForStringId(*string_id);
  }

  // String is not in the DEX file. Assign a new ID to it which is higher than
  // the number of strings in the DEX file.

  // We use the main `VerifierDeps` for adding new strings to simplify
  // synchronization/merging of these entries between threads.
  VerifierDeps* singleton = GetMainVerifierDeps(this);
  DexFileDeps* deps = singleton->GetDexFileDeps(dex_file);
  DCHECK(deps != nullptr);

  uint32_t num_ids_in_dex = dex_file.NumStringIds();
  uint32_t found_id;

  {
    ReaderMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
    if (FindExistingStringId(deps->strings_, str, &found_id)) {
      return dex::StringIndex(num_ids_in_dex + found_id);
    }
  }
  {
    WriterMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
    if (FindExistingStringId(deps->strings_, str, &found_id)) {
      return dex::StringIndex(num_ids_in_dex + found_id);
    }
    deps->strings_.push_back(str);
    dex::StringIndex new_id(num_ids_in_dex + deps->strings_.size() - 1);
    CHECK_GE(new_id.index_, num_ids_in_dex);  // check for overflows
    DCHECK_EQ(str, singleton->GetStringFromId(dex_file, new_id));
    return new_id;
  }
}

std::string VerifierDeps::GetStringFromId(const DexFile& dex_file,
                                          dex::StringIndex string_id) const {
  uint32_t num_ids_in_dex = dex_file.NumStringIds();
  if (string_id.index_ < num_ids_in_dex) {
    return std::string(dex_file.StringDataByIdx(string_id));
  } else {
    const DexFileDeps* deps = GetDexFileDeps(dex_file);
    DCHECK(deps != nullptr);
    string_id.index_ -= num_ids_in_dex;
    CHECK_LT(string_id.index_, deps->strings_.size());
    return deps->strings_[string_id.index_];
  }
}

void VerifierDeps::AddAssignability(const DexFile& dex_file,
                                    const dex::ClassDef& class_def,
                                    ObjPtr<mirror::Class> destination,
                                    ObjPtr<mirror::Class> source) {
  // Test that the method is only called on reference types.
  // Note that concurrent verification of `destination` and `source` may have
  // set their status to erroneous. However, the tests performed below rely
  // merely on no issues with linking (valid access flags, superclass and
  // implemented interfaces). If the class at any point reached the IsResolved
  // status, the requirement holds. This is guaranteed by RegTypeCache::ResolveClass.
  DCHECK(destination != nullptr);
  DCHECK(source != nullptr);

  if (destination->IsPrimitive() || source->IsPrimitive()) {
    // Primitive types are trivially non-assignable to anything else.
    // We do not need to record trivial assignability, as it will
    // not change across releases.
    return;
  }

  if (destination == source || destination->IsObjectClass()) {
    // Cases when `destination` is trivially assignable from `source`.
    return;
  }

  if (destination->IsArrayClass() && source->IsArrayClass()) {
    // Both types are arrays. Break down to component types and add recursively.
    // This helps filter out destinations from compiled DEX files (see below)
    // and deduplicate entries with the same canonical component type.
    ObjPtr<mirror::Class> destination_component = destination->GetComponentType();
    ObjPtr<mirror::Class> source_component = source->GetComponentType();

    // Only perform the optimization if both types are resolved which guarantees
    // that they linked successfully, as required at the top of this method.
    if (destination_component->IsResolved() && source_component->IsResolved()) {
      AddAssignability(dex_file, class_def, destination_component, source_component);
      return;
    }
  }

  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
  if (dex_deps == nullptr) {
    // This invocation is from verification of a DEX file which is not being compiled.
    return;
  }

  // Get string IDs for both descriptors and store in the appropriate set.
  dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination);
  dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source);

  uint16_t index = dex_file.GetIndexForClassDef(class_def);
  dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
}

void VerifierDeps::AddAssignability(const DexFile& dex_file,
                                    const dex::ClassDef& class_def,
                                    const RegType& destination,
                                    const RegType& source) {
  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
  if (dex_deps == nullptr) {
    // This invocation is from verification of a DEX file which is not being compiled.
    return;
  }

  CHECK(destination.IsUnresolvedReference() || destination.HasClass());
  CHECK(!destination.IsUnresolvedMergedReference());

  if (source.IsUnresolvedReference() || source.HasClass()) {
    // Get string IDs for both descriptors and store in the appropriate set.
    dex::StringIndex destination_id =
        GetIdFromString(dex_file, std::string(destination.GetDescriptor()));
    dex::StringIndex source_id = GetIdFromString(dex_file, std::string(source.GetDescriptor()));
    uint16_t index = dex_file.GetIndexForClassDef(class_def);
    dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
  } else if (source.IsZeroOrNull()) {
    // Nothing to record, null is always assignable.
  } else {
    CHECK(source.IsUnresolvedMergedReference()) << source.Dump();
    const UnresolvedMergedType& merge = *down_cast<const UnresolvedMergedType*>(&source);
    AddAssignability(dex_file, class_def, destination, merge.GetResolvedPart());
    for (uint32_t idx : merge.GetUnresolvedTypes().Indexes()) {
      AddAssignability(dex_file, class_def, destination, merge.GetRegTypeCache()->GetFromId(idx));
    }
  }
}

void VerifierDeps::MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
                                                 const DexFile& dex_file,
                                                 const dex::ClassDef& class_def,
                                                 FailureKind failure_kind) {
  if (verifier_deps != nullptr) {
    switch (failure_kind) {
      case verifier::FailureKind::kHardFailure:
      case verifier::FailureKind::kSoftFailure: {
        // Class will be verified at runtime.
        DexFileDeps* dex_deps = verifier_deps->GetDexFileDeps(dex_file);
        uint16_t index = dex_file.GetIndexForClassDef(class_def);
        dex_deps->assignable_types_[index].clear();
        break;
      }
      case verifier::FailureKind::kAccessChecksFailure:
      case verifier::FailureKind::kTypeChecksFailure:
      case verifier::FailureKind::kNoFailure: {
        verifier_deps->RecordClassVerified(dex_file, class_def);
        break;
      }
    }
  }
}

void VerifierDeps::RecordClassVerified(const DexFile& dex_file, const dex::ClassDef& class_def) {
  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
  DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
  dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
}

bool VerifierDeps::HasRecordedVerifiedStatus(const DexFile& dex_file,
                                             const dex::ClassDef& class_def) {
  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
  DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
  return dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)];
}

void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
                                            const DexFile& dex_file,
                                            const dex::ClassDef& class_def,
                                            ObjPtr<mirror::Class> destination,
                                            ObjPtr<mirror::Class> source) {
  if (verifier_deps != nullptr) {
    verifier_deps->AddAssignability(dex_file, class_def, destination, source);
  }
}

void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
                                            const DexFile& dex_file,
                                            const dex::ClassDef& class_def,
                                            const RegType& destination,
                                            const RegType& source) {
  if (verifier_deps != nullptr) {
    verifier_deps->AddAssignability(dex_file, class_def, destination, source);
  }
}

namespace {

template <typename T>
inline uint32_t Encode(T in);

template <>
inline uint32_t Encode<dex::StringIndex>(dex::StringIndex in) {
  return in.index_;
}

template <typename T>
inline T Decode(uint32_t in);

template <>
inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) {
  return dex::StringIndex(in);
}

template <typename T1, typename T2>
static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) {
  EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
  EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
}

template <typename T1, typename T2>
static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
  uint32_t v1, v2;
  if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2))) {
    return false;
  }
  *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2));
  return true;
}

template <typename T1, typename T2, typename T3>
static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2, T3>& t) {
  EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
  EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
  EncodeUnsignedLeb128(out, Encode(std::get<2>(t)));
}

template <typename T1, typename T2, typename T3>
static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
  uint32_t v1, v2, v3;
  if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2)) ||
      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v3))) {
    return false;
  }
  *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2), Decode<T3>(v3));
  return true;
}

static void SetUint32InUint8Array(std::vector<uint8_t>* out,
                                  uint32_t uint8_offset,
                                  uint32_t uint32_offset,
                                  uint32_t value) {
  DCHECK(IsAligned<sizeof(uint32_t)>(out->data() + uint8_offset));
  (reinterpret_cast<uint32_t*>(out->data() + uint8_offset))[uint32_offset] = value;
}

template <typename T>
static void EncodeSetVector(std::vector<uint8_t>* out,
                            const std::vector<std::set<T>>& vector,
                            const std::vector<bool>& verified_classes) {
  uint32_t offsets_index = out->size();
  // Make room for offsets for each class, +1 for marking the end of the
  // assignability types data.
  out->resize(out->size() + (vector.size() + 1) * sizeof(uint32_t));
  uint32_t class_def_index = 0;
  for (const std::set<T>& set : vector) {
    if (verified_classes[class_def_index]) {
      // Store the offset of the set for this class.
      SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
      for (const T& entry : set) {
        EncodeTuple(out, entry);
      }
    } else {
      SetUint32InUint8Array(out, offsets_index, class_def_index, VerifierDeps::kNotVerifiedMarker);
    }
    class_def_index++;
  }
  SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
}

template <bool kFillSet, typename T>
static bool DecodeSetVector(const uint8_t** cursor,
                            const uint8_t* start,
                            const uint8_t* end,
                            std::vector<std::set<T>>* vector,
                            std::vector<bool>* verified_classes,
                            size_t num_class_defs) {
  const uint32_t* offsets = reinterpret_cast<const uint32_t*>(*cursor);
  uint32_t next_valid_offset_index = 1;
  // Put the cursor after the offsets of each class, +1 for the offset of the
  // end of the assignable types data.
  *cursor += (num_class_defs + 1) * sizeof(uint32_t);
  for (uint32_t i = 0; i < num_class_defs; ++i) {
    uint32_t offset = offsets[i];
    if (offset == VerifierDeps::kNotVerifiedMarker) {
      (*verified_classes)[i] = false;
      continue;
    }
    (*verified_classes)[i] = true;
    *cursor = start + offset;
    // Fetch the assignability checks.
    std::set<T>& set = (*vector)[i];
    // Find the offset of the next entry. This will tell us where to stop when
    // reading the checks. Note that the last entry in the `offsets` array points
    // to the end of the assignability types data, so the loop will terminate correctly.
    while (next_valid_offset_index <= i ||
           offsets[next_valid_offset_index] == VerifierDeps::kNotVerifiedMarker) {
      next_valid_offset_index++;
    }
    const uint8_t* set_end = start + offsets[next_valid_offset_index];
    // Decode each check.
    while (*cursor < set_end) {
      T tuple;
      if (UNLIKELY(!DecodeTuple(cursor, end, &tuple))) {
        return false;
      }
      if (kFillSet) {
        set.emplace(tuple);
      }
    }
  }
  // Align the cursor to start decoding the strings.
  *cursor = AlignUp(*cursor, sizeof(uint32_t));
  return true;
}

static inline void EncodeStringVector(std::vector<uint8_t>* out,
                                      const std::vector<std::string>& strings) {
  uint32_t offsets_index = out->size();
  // Make room for offsets for each string, +1 for putting the number of
  // strings.
  out->resize(out->size() + (strings.size() + 1) * sizeof(uint32_t));
  (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[0] = strings.size();
  uint32_t string_index = 1;
  for (const std::string& str : strings) {
    // Store the offset of the string.
    (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[string_index++] = out->size();

    // Store the string data.
    const uint8_t* data = reinterpret_cast<const uint8_t*>(str.c_str());
    size_t length = str.length() + 1;
    out->insert(out->end(), data, data + length);
    DCHECK_EQ(0u, out->back());
  }
}

template <bool kFillVector>
static inline bool DecodeStringVector(const uint8_t** cursor,
                                      const uint8_t* start,
                                      const uint8_t* end,
                                      std::vector<std::string>* strings) {
  DCHECK(strings->empty());
  uint32_t num_strings = reinterpret_cast<const uint32_t*>(*cursor)[0];
  if (kFillVector) {
    strings->reserve(num_strings);
  }
  const uint8_t* offsets = *cursor;
  *cursor += sizeof(uint32_t) + num_strings * sizeof(uint32_t);
  for (uint32_t i = 0; i < num_strings; ++i) {
    uint32_t string_offset = reinterpret_cast<const uint32_t*>(offsets)[i + 1];
    const char* string_start = reinterpret_cast<const char*>(start + string_offset);
    const char* string_end =
        reinterpret_cast<const char*>(memchr(string_start, 0, end - start - string_offset));
    if (UNLIKELY(string_end == nullptr)) {
      return false;
    }
    size_t string_length = string_end - string_start;
    if (kFillVector) {
      strings->emplace_back(string_start, string_length);
    }
    *cursor = reinterpret_cast<const uint8_t*>(string_end + 1);
  }
  return true;
}

}  // namespace

void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files,
                          std::vector<uint8_t>* buffer) const {
  DCHECK(buffer->empty());
  buffer->resize(dex_files.size() * sizeof(uint32_t));
  uint32_t dex_file_index = 0;
  for (const DexFile* dex_file : dex_files) {
    // Four byte alignment before encoding the data.
    buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
    (reinterpret_cast<uint32_t*>(buffer->data()))[dex_file_index++] = buffer->size();
    const DexFileDeps& deps = *GetDexFileDeps(*dex_file);
    EncodeSetVector(buffer, deps.assignable_types_, deps.verified_classes_);
    // Four byte alignment before encoding strings.
    buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
    EncodeStringVector(buffer, deps.strings_);
  }
}

template <bool kOnlyVerifiedClasses>
bool VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps,
                                     const uint8_t** cursor,
                                     const uint8_t* data_start,
                                     const uint8_t* data_end,
                                     size_t num_class_defs) {
  return DecodeSetVector</*kFillSet=*/!kOnlyVerifiedClasses>(cursor,
                                                             data_start,
                                                             data_end,
                                                             &deps.assignable_types_,
                                                             &deps.verified_classes_,
                                                             num_class_defs) &&
         DecodeStringVector</*kFillVector=*/!kOnlyVerifiedClasses>(
             cursor, data_start, data_end, &deps.strings_);
}

bool VerifierDeps::ParseStoredData(const std::vector<const DexFile*>& dex_files,
                                   ArrayRef<const uint8_t> data) {
  if (data.empty()) {
    // Return eagerly, as the first thing we expect from VerifierDeps data is
    // the number of created strings, even if there is no dependency.
    // Currently, only the boot image does not have any VerifierDeps data.
    return true;
  }
  const uint8_t* data_start = data.data();
  const uint8_t* data_end = data_start + data.size();
  const uint8_t* cursor = data_start;
  uint32_t dex_file_index = 0;
  for (const DexFile* dex_file : dex_files) {
    DexFileDeps* deps = GetDexFileDeps(*dex_file);
    // Fetch the offset of this dex file's verifier data.
    cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
    size_t num_class_defs = dex_file->NumClassDefs();
    if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/false>(
            *deps, &cursor, data_start, data_end, num_class_defs))) {
      LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
      return false;
    }
  }
  // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
  return true;
}

bool VerifierDeps::ParseVerifiedClasses(
    const std::vector<const DexFile*>& dex_files,
    ArrayRef<const uint8_t> data,
    /*out*/ std::vector<std::vector<bool>>* verified_classes_per_dex) {
  DCHECK(!data.empty());
  DCHECK(!dex_files.empty());
  DCHECK(verified_classes_per_dex->empty());

  verified_classes_per_dex->reserve(dex_files.size());

  const uint8_t* data_start = data.data();
  const uint8_t* data_end = data_start + data.size();
  const uint8_t* cursor = data_start;
  uint32_t dex_file_index = 0;
  for (const DexFile* dex_file : dex_files) {
    DexFileDeps deps(/*num_class_defs=*/0u);  // Do not initialize vectors.
    // Fetch the offset of this dex file's verifier data.
    cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
    size_t num_class_defs = dex_file->NumClassDefs();
    deps.verified_classes_.resize(num_class_defs);
    if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/true>(
            deps, &cursor, data_start, data_end, num_class_defs))) {
      LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
      return false;
    }
    verified_classes_per_dex->push_back(std::move(deps.verified_classes_));
  }
  // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
  return true;
}

bool VerifierDeps::Equals(const VerifierDeps& rhs) const {
  if (dex_deps_.size() != rhs.dex_deps_.size()) {
    return false;
  }

  auto lhs_it = dex_deps_.begin();
  auto rhs_it = rhs.dex_deps_.begin();

  for (; (lhs_it != dex_deps_.end()) && (rhs_it != rhs.dex_deps_.end()); lhs_it++, rhs_it++) {
    const DexFile* lhs_dex_file = lhs_it->first;
    const DexFile* rhs_dex_file = rhs_it->first;
    if (lhs_dex_file != rhs_dex_file) {
      return false;
    }

    DexFileDeps* lhs_deps = lhs_it->second.get();
    DexFileDeps* rhs_deps = rhs_it->second.get();
    if (!lhs_deps->Equals(*rhs_deps)) {
      return false;
    }
  }

  DCHECK((lhs_it == dex_deps_.end()) && (rhs_it == rhs.dex_deps_.end()));
  return true;
}

bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const {
  return (strings_ == rhs.strings_) && (assignable_types_ == rhs.assignable_types_) &&
         (verified_classes_ == rhs.verified_classes_);
}

void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const {
  // Sort dex files by their location to ensure deterministic ordering.
  using DepsEntry = std::pair<const DexFile*, const DexFileDeps*>;
  std::vector<DepsEntry> dex_deps;
  dex_deps.reserve(dex_deps_.size());
  for (const auto& dep : dex_deps_) {
    dex_deps.emplace_back(dep.first, dep.second.get());
  }
  std::sort(dex_deps.begin(), dex_deps.end(), [](const DepsEntry& lhs, const DepsEntry& rhs) {
    return lhs.first->GetLocation() < rhs.first->GetLocation();
  });
  for (const auto& dep : dex_deps) {
    const DexFile& dex_file = *dep.first;
    vios->Stream() << "Dependencies of " << dex_file.GetLocation() << ":\n";

    ScopedIndentation indent(vios);

    for (const std::string& str : dep.second->strings_) {
      vios->Stream() << "Extra string: " << str << "\n";
    }

    for (size_t idx = 0; idx < dep.second->assignable_types_.size(); idx++) {
      vios->Stream() << "Dependencies of " << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
                     << ":\n";
      for (const TypeAssignability& entry : dep.second->assignable_types_[idx]) {
        vios->Stream() << GetStringFromId(dex_file, entry.GetSource()) << " must be assignable to "
                       << GetStringFromId(dex_file, entry.GetDestination()) << "\n";
      }
    }

    for (size_t idx = 0; idx < dep.second->verified_classes_.size(); idx++) {
      if (!dep.second->verified_classes_[idx]) {
        vios->Stream() << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
                       << " will be verified at runtime\n";
      }
    }
  }
}

bool VerifierDeps::ValidateDependencies(Thread* self,
                                        Handle<mirror::ClassLoader> class_loader,
                                        const std::vector<const DexFile*>& dex_files,
                                        /* out */ std::string* error_msg) const {
  for (const auto* dex_file : dex_files) {
    const DexFileDeps* my_deps = GetDexFileDeps(*dex_file);
    if (!VerifyDexFile(class_loader, *dex_file, *my_deps, self, error_msg)) {
      return false;
    }
  }
  return true;
}

// TODO: share that helper with other parts of the compiler that have
// the same lookup pattern.
static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
                                                        Thread* self,
                                                        const std::string& name,
                                                        Handle<mirror::ClassLoader> class_loader)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> result = class_linker->FindClass(self, name.c_str(), class_loader);
  if (result == nullptr) {
    DCHECK(self->IsExceptionPending());
    self->ClearException();
  }
  return result;
}

bool VerifierDeps::VerifyAssignability(Handle<mirror::ClassLoader> class_loader,
                                       const DexFile& dex_file,
                                       const std::vector<std::set<TypeAssignability>>& assignables,
                                       Thread* self,
                                       /* out */ std::string* error_msg) const {
  StackHandleScope<2> hs(self);
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
  MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));

  for (const auto& vec : assignables) {
    for (const auto& entry : vec) {
      const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
      destination.Assign(
          FindClassAndClearException(class_linker, self, destination_desc, class_loader));
      const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
      source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader));

      if (destination == nullptr || source == nullptr) {
        // We currently don't use assignability information for unresolved
        // types, as the status of the class using unresolved types will be soft
        // fail in the vdex.
        continue;
      }

      DCHECK(destination->IsResolved() && source->IsResolved());
      if (!destination->IsAssignableFrom(source.Get())) {
        *error_msg = ART_FORMAT("Class {} not assignable from {}", destination_desc, source_desc);
        return false;
      }
    }
  }
  return true;
}

void VerifierDeps::ClearData(const std::vector<const DexFile*>& dex_files) {
  for (const DexFile* dex_file : dex_files) {
    auto it = dex_deps_.find(dex_file);
    if (it == dex_deps_.end()) {
      continue;
    }
    std::unique_ptr<DexFileDeps> deps(new DexFileDeps(dex_file->NumClassDefs()));
    it->second.swap(deps);
  }
}

bool VerifierDeps::VerifyDexFile(Handle<mirror::ClassLoader> class_loader,
                                 const DexFile& dex_file,
                                 const DexFileDeps& deps,
                                 Thread* self,
                                 /* out */ std::string* error_msg) const {
  return VerifyAssignability(class_loader, dex_file, deps.assignable_types_, self, error_msg);
}

}  // namespace verifier
}  // namespace art
