// Copyright 2015 The Crashpad Authors
//
// 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 "snapshot/minidump/process_snapshot_minidump.h"

#include <utility>

#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "minidump/minidump_extensions.h"
#include "snapshot/memory_map_region_snapshot.h"
#include "snapshot/minidump/minidump_simple_string_dictionary_reader.h"
#include "snapshot/minidump/minidump_string_reader.h"
#include "util/file/file_io.h"

namespace crashpad {

namespace internal {

class MemoryMapRegionSnapshotMinidump : public MemoryMapRegionSnapshot {
 public:
  MemoryMapRegionSnapshotMinidump(MINIDUMP_MEMORY_INFO info) : info_(info) {}
  ~MemoryMapRegionSnapshotMinidump() override = default;

  const MINIDUMP_MEMORY_INFO& AsMinidumpMemoryInfo() const override {
    return info_;
  }

 private:
  MINIDUMP_MEMORY_INFO info_;
};

}  // namespace internal

ProcessSnapshotMinidump::ProcessSnapshotMinidump()
    : ProcessSnapshot(),
      header_(),
      stream_directory_(),
      stream_map_(),
      modules_(),
      threads_(),
      unloaded_modules_(),
      mem_regions_(),
      mem_regions_exposed_(),
      custom_streams_(),
      crashpad_info_(),
      system_snapshot_(),
      exception_snapshot_(),
      arch_(CPUArchitecture::kCPUArchitectureUnknown),
      annotations_simple_map_(),
      file_reader_(nullptr),
      process_id_(kInvalidProcessID),
      create_time_(0),
      user_time_(0),
      kernel_time_(0),
      initialized_() {}

ProcessSnapshotMinidump::~ProcessSnapshotMinidump() {}

bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  file_reader_ = file_reader;

  if (!file_reader_->SeekSet(0)) {
    return false;
  }

  if (!file_reader_->ReadExactly(&header_, sizeof(header_))) {
    return false;
  }

  if (header_.Signature != MINIDUMP_SIGNATURE) {
    LOG(ERROR) << "minidump signature mismatch";
    return false;
  }

  if (header_.Version != MINIDUMP_VERSION) {
    LOG(ERROR) << "minidump version mismatch";
    return false;
  }

  if (!file_reader->SeekSet(header_.StreamDirectoryRva)) {
    return false;
  }

  stream_directory_.resize(header_.NumberOfStreams);
  if (!stream_directory_.empty() &&
      !file_reader_->ReadExactly(
          &stream_directory_[0],
          header_.NumberOfStreams * sizeof(stream_directory_[0]))) {
    return false;
  }

  for (const MINIDUMP_DIRECTORY& directory : stream_directory_) {
    const MinidumpStreamType stream_type =
        static_cast<MinidumpStreamType>(directory.StreamType);
    if (stream_map_.find(stream_type) != stream_map_.end()) {
      LOG(ERROR) << "duplicate streams for type " << directory.StreamType;
      return false;
    }

    stream_map_[stream_type] = &directory.Location;
  }

  if (!InitializeCrashpadInfo() || !InitializeMiscInfo() ||
      !InitializeModules() || !InitializeSystemSnapshot() ||
      !InitializeMemoryInfo() || !InitializeExtraMemory() ||
      !InitializeThreads() || !InitializeCustomMinidumpStreams() ||
      !InitializeExceptionSnapshot()) {
    return false;
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

crashpad::ProcessID ProcessSnapshotMinidump::ProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return process_id_;
}

crashpad::ProcessID ProcessSnapshotMinidump::ParentProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
}

void ProcessSnapshotMinidump::SnapshotTime(timeval* snapshot_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  snapshot_time->tv_sec = header_.TimeDateStamp;
  snapshot_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  start_time->tv_sec = create_time_;
  start_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ProcessCPUTimes(timeval* user_time,
                                              timeval* system_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  user_time->tv_sec = user_time_;
  user_time->tv_usec = 0;
  system_time->tv_sec = kernel_time_;
  system_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ReportID(UUID* report_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *report_id = crashpad_info_.report_id;
}

void ProcessSnapshotMinidump::ClientID(UUID* client_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *client_id = crashpad_info_.client_id;
}

const std::map<std::string, std::string>&
ProcessSnapshotMinidump::AnnotationsSimpleMap() const {
  // TODO(mark): This method should not be const, although the interface
  // currently imposes this requirement. Making it non-const would allow
  // annotations_simple_map_ to be lazily constructed: InitializeCrashpadInfo()
  // could be called here, and from other locations that require it, rather than
  // calling it from Initialize().
  // https://crashpad.chromium.org/bug/9
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return annotations_simple_map_;
}

const SystemSnapshot* ProcessSnapshotMinidump::System() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return &system_snapshot_;
}

std::vector<const ThreadSnapshot*> ProcessSnapshotMinidump::Threads() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const ThreadSnapshot*> threads;
  for (const auto& thread : threads_) {
    threads.push_back(thread.get());
  }
  return threads;
}

std::vector<const ModuleSnapshot*> ProcessSnapshotMinidump::Modules() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const ModuleSnapshot*> modules;
  for (const auto& module : modules_) {
    modules.push_back(module.get());
  }
  return modules;
}

std::vector<UnloadedModuleSnapshot> ProcessSnapshotMinidump::UnloadedModules()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
}

const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  if (exception_snapshot_.IsValid()) {
    return &exception_snapshot_;
  }
  // Allow caller to know whether the minidump contained an exception stream.
  return nullptr;
}

std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotMinidump::MemoryMap()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return mem_regions_exposed_;
}

std::vector<HandleSnapshot> ProcessSnapshotMinidump::Handles() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
}

std::vector<const MemorySnapshot*> ProcessSnapshotMinidump::ExtraMemory()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const MemorySnapshot*> chunks;
  for (const auto& chunk : extra_memory_) {
    chunks.push_back(chunk.get());
  }
  return chunks;
}

const ProcessMemory* ProcessSnapshotMinidump::Memory() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return nullptr;
}

std::vector<const MinidumpStream*>
ProcessSnapshotMinidump::CustomMinidumpStreams() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::vector<const MinidumpStream*> result;
  result.reserve(custom_streams_.size());
  for (const auto& custom_stream : custom_streams_) {
    result.push_back(custom_stream.get());
  }
  return result;
}

bool ProcessSnapshotMinidump::InitializeCrashpadInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  constexpr size_t crashpad_info_min_size =
      offsetof(decltype(crashpad_info_), reserved);
  size_t remaining_data_size = stream_it->second->DataSize;
  if (remaining_data_size < crashpad_info_min_size) {
    LOG(ERROR) << "crashpad_info size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  if (!file_reader_->ReadExactly(&crashpad_info_, crashpad_info_min_size)) {
    return false;
  }
  remaining_data_size -= crashpad_info_min_size;

  // Read `reserved` if available.
  size_t crashpad_reserved_size = sizeof(crashpad_info_.reserved);
  if (remaining_data_size >= crashpad_reserved_size) {
    if (!file_reader_->ReadExactly(&crashpad_info_.reserved,
                                   crashpad_reserved_size)) {
      return false;
    }
    remaining_data_size -= crashpad_reserved_size;
  } else {
    crashpad_info_.reserved = 0;
  }

  // Read `address_mask` if available.
  size_t crashpad_address_mask_size = sizeof(crashpad_info_.address_mask);
  if (remaining_data_size >= crashpad_address_mask_size) {
    if (!file_reader_->ReadExactly(&crashpad_info_.address_mask,
                                   crashpad_address_mask_size)) {
      return false;
    }
    remaining_data_size -= crashpad_address_mask_size;
  } else {
    crashpad_info_.address_mask = 0;
  }

  if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
    LOG(ERROR) << "crashpad_info version mismatch";
    return false;
  }

  return internal::ReadMinidumpSimpleStringDictionary(
      file_reader_,
      crashpad_info_.simple_annotations,
      &annotations_simple_map_);
}

bool ProcessSnapshotMinidump::InitializeMiscInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMiscInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  const size_t size = stream_it->second->DataSize;
  if (size != sizeof(MINIDUMP_MISC_INFO_5) &&
      size != sizeof(MINIDUMP_MISC_INFO_4) &&
      size != sizeof(MINIDUMP_MISC_INFO_3) &&
      size != sizeof(MINIDUMP_MISC_INFO_2) &&
      size != sizeof(MINIDUMP_MISC_INFO)) {
    LOG(ERROR) << "misc_info size mismatch";
    return false;
  }

  MINIDUMP_MISC_INFO_5 info;
  if (!file_reader_->ReadExactly(&info, size)) {
    return false;
  }

  switch (stream_it->second->DataSize) {
    case sizeof(MINIDUMP_MISC_INFO_5):
    case sizeof(MINIDUMP_MISC_INFO_4):
#if defined(WCHAR_T_IS_16_BIT)
      full_version_ = base::WideToUTF8(info.BuildString);
#else
      full_version_ = base::UTF16ToUTF8(info.BuildString);
#endif
      full_version_ = full_version_.substr(0, full_version_.find(';'));
      [[fallthrough]];
    case sizeof(MINIDUMP_MISC_INFO_3):
    case sizeof(MINIDUMP_MISC_INFO_2):
    case sizeof(MINIDUMP_MISC_INFO):
      // TODO(jperaza): Save the remaining misc info.
      // https://crashpad.chromium.org/bug/10
      process_id_ = info.ProcessId;
      create_time_ = info.ProcessCreateTime;
      user_time_ = info.ProcessUserTime;
      kernel_time_ = info.ProcessKernelTime;
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeModules() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeModuleList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR> module_crashpad_info_links;
  if (!InitializeModulesCrashpadInfo(&module_crashpad_info_links)) {
    return false;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_MODULE_LIST)) {
    LOG(ERROR) << "module_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  uint32_t module_count;
  if (!file_reader_->ReadExactly(&module_count, sizeof(module_count))) {
    return false;
  }

  if (sizeof(MINIDUMP_MODULE_LIST) + module_count * sizeof(MINIDUMP_MODULE) !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "module_list size mismatch";
    return false;
  }

  for (uint32_t module_index = 0; module_index < module_count; ++module_index) {
    const RVA module_rva = stream_it->second->Rva + sizeof(module_count) +
                           module_index * sizeof(MINIDUMP_MODULE);

    const auto& module_crashpad_info_it =
        module_crashpad_info_links.find(module_index);
    const MINIDUMP_LOCATION_DESCRIPTOR* module_crashpad_info_location =
        module_crashpad_info_it != module_crashpad_info_links.end()
            ? &module_crashpad_info_it->second
            : nullptr;

    auto module = std::make_unique<internal::ModuleSnapshotMinidump>();
    if (!module->Initialize(
            file_reader_, module_rva, module_crashpad_info_location)) {
      return false;
    }

    modules_.push_back(std::move(module));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeModulesCrashpadInfo(
    std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR>*
        module_crashpad_info_links) {
  module_crashpad_info_links->clear();

  if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
    return false;
  }

  if (crashpad_info_.module_list.Rva == 0) {
    return true;
  }

  if (crashpad_info_.module_list.DataSize <
      sizeof(MinidumpModuleCrashpadInfoList)) {
    LOG(ERROR) << "module_crashpad_info_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(crashpad_info_.module_list.Rva)) {
    return false;
  }

  uint32_t crashpad_module_count;
  if (!file_reader_->ReadExactly(&crashpad_module_count,
                                 sizeof(crashpad_module_count))) {
    return false;
  }

  if (crashpad_info_.module_list.DataSize !=
      sizeof(MinidumpModuleCrashpadInfoList) +
          crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink)) {
    LOG(ERROR) << "module_crashpad_info_list size mismatch";
    return false;
  }

  std::unique_ptr<MinidumpModuleCrashpadInfoLink[]> minidump_links(
      new MinidumpModuleCrashpadInfoLink[crashpad_module_count]);
  if (!file_reader_->ReadExactly(
          &minidump_links[0],
          crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink))) {
    return false;
  }

  for (uint32_t crashpad_module_index = 0;
       crashpad_module_index < crashpad_module_count;
       ++crashpad_module_index) {
    const MinidumpModuleCrashpadInfoLink& minidump_link =
        minidump_links[crashpad_module_index];
    if (!module_crashpad_info_links
             ->insert(std::make_pair(minidump_link.minidump_module_list_index,
                                     minidump_link.location))
             .second) {
      LOG(WARNING)
          << "duplicate module_crashpad_info_list minidump_module_list_index "
          << minidump_link.minidump_module_list_index;
      return false;
    }
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeMemoryInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMemoryInfoList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_MEMORY_INFO_LIST)) {
    LOG(ERROR) << "memory_info_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  MINIDUMP_MEMORY_INFO_LIST list;

  if (!file_reader_->ReadExactly(&list, sizeof(list))) {
    return false;
  }

  if (list.SizeOfHeader != sizeof(list)) {
    return false;
  }

  if (list.SizeOfEntry != sizeof(MINIDUMP_MEMORY_INFO)) {
    return false;
  }

  if (sizeof(MINIDUMP_MEMORY_INFO_LIST) +
          list.NumberOfEntries * list.SizeOfEntry !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "memory_info_list size mismatch";
    return false;
  }

  for (uint32_t i = 0; i < list.NumberOfEntries; i++) {
    MINIDUMP_MEMORY_INFO info;

    if (!file_reader_->ReadExactly(&info, sizeof(info))) {
      return false;
    }

    mem_regions_.emplace_back(
        std::make_unique<internal::MemoryMapRegionSnapshotMinidump>(info));
    mem_regions_exposed_.emplace_back(mem_regions_.back().get());
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeExtraMemory() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMemoryList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_MEMORY_LIST)) {
    LOG(ERROR) << "memory_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  // MSVC won't let us stack-allocate a MINIDUMP_MEMORY_LIST because of its
  // trailing zero-element array. Luckily we're only interested in its other
  // field anyway: a uint32_t indicating the number of memory descriptors that
  // follow.
  static_assert(
      sizeof(MINIDUMP_MEMORY_LIST) == 4,
      "MINIDUMP_MEMORY_LIST's only actual field should be an uint32_t");
  uint32_t num_ranges;
  if (!file_reader_->ReadExactly(&num_ranges, sizeof(num_ranges))) {
    return false;
  }

  // We have to manually keep track of the locations of the entries in the
  // contiguous list of MINIDUMP_MEMORY_DESCRIPTORs, because the Initialize()
  // function jumps around the file to find the contents of each snapshot.
  FileOffset location = file_reader_->SeekGet();
  for (uint32_t i = 0; i < num_ranges; i++) {
    extra_memory_.emplace_back(
        std::make_unique<internal::MemorySnapshotMinidump>());
    if (!extra_memory_.back()->Initialize(file_reader_,
                                          static_cast<RVA>(location))) {
      return false;
    }
    location += sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeThreads() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_THREAD_LIST)) {
    LOG(ERROR) << "thread_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  uint32_t thread_count;
  if (!file_reader_->ReadExactly(&thread_count, sizeof(thread_count))) {
    return false;
  }

  if (sizeof(MINIDUMP_THREAD_LIST) + thread_count * sizeof(MINIDUMP_THREAD) !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "thread_list size mismatch";
    return false;
  }

  if (!InitializeThreadNames()) {
    return false;
  }

  for (uint32_t thread_index = 0; thread_index < thread_count; ++thread_index) {
    const RVA thread_rva = stream_it->second->Rva + sizeof(thread_count) +
                           thread_index * sizeof(MINIDUMP_THREAD);

    auto thread = std::make_unique<internal::ThreadSnapshotMinidump>();
    if (!thread->Initialize(file_reader_, thread_rva, arch_, thread_names_)) {
      return false;
    }

    threads_.push_back(std::move(thread));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeThreadNames() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadNameList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_THREAD_NAME_LIST)) {
    LOG(ERROR) << "thread_name_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  uint32_t thread_name_count;
  if (!file_reader_->ReadExactly(&thread_name_count,
                                 sizeof(thread_name_count))) {
    return false;
  }

  if (sizeof(MINIDUMP_THREAD_NAME_LIST) +
          thread_name_count * sizeof(MINIDUMP_THREAD_NAME) !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "thread_name_list size mismatch";
    return false;
  }

  for (uint32_t thread_name_index = 0; thread_name_index < thread_name_count;
       ++thread_name_index) {
    const RVA thread_name_rva =
        stream_it->second->Rva + sizeof(thread_name_count) +
        thread_name_index * sizeof(MINIDUMP_THREAD_NAME);
    if (!file_reader_->SeekSet(thread_name_rva)) {
      return false;
    }
    MINIDUMP_THREAD_NAME minidump_thread_name;
    if (!file_reader_->ReadExactly(&minidump_thread_name,
                                   sizeof(minidump_thread_name))) {
      return false;
    }
    std::string name;
    if (!internal::ReadMinidumpUTF16String(
            file_reader_, minidump_thread_name.RvaOfThreadName, &name)) {
      return false;
    }

    // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
    const uint32_t thread_id = minidump_thread_name.ThreadId;
    thread_names_.emplace(thread_id, std::move(name));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeSystemSnapshot() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeSystemInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_SYSTEM_INFO)) {
    LOG(ERROR) << "system info size mismatch";
    return false;
  }

  if (!system_snapshot_.Initialize(
          file_reader_, stream_it->second->Rva, full_version_)) {
    return false;
  }

  arch_ = system_snapshot_.GetCPUArchitecture();
  return true;
}

bool ProcessSnapshotMinidump::InitializeCustomMinidumpStreams() {
  for (size_t i = 0; i < stream_directory_.size(); i++) {
    const auto& stream = stream_directory_[i];

    // Filter out reserved minidump and crashpad streams.
    const uint32_t stream_type = stream.StreamType;
    if (stream_type <=
            MinidumpStreamType::kMinidumpStreamTypeLastReservedStream ||
        (stream_type >= MinidumpStreamType::kMinidumpStreamTypeCrashpadInfo &&
         stream_type <= MinidumpStreamType::
                            kMinidumpStreamTypeCrashpadLastReservedStream)) {
      continue;
    }

    std::vector<uint8_t> data(stream.Location.DataSize);
    if (!file_reader_->SeekSet(stream.Location.Rva) ||
        !file_reader_->ReadExactly(data.data(), data.size())) {
      LOG(ERROR) << "Failed to read stream with ID 0x" << std::hex
                 << stream_type << std::dec << " at index " << i;
      return false;
    }

    custom_streams_.push_back(
        std::make_unique<MinidumpStream>(stream_type, std::move(data)));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeExceptionSnapshot() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeException);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_EXCEPTION_STREAM)) {
    LOG(ERROR) << "system info size mismatch";
    return false;
  }

  if (!exception_snapshot_.Initialize(
          file_reader_, arch_, stream_it->second->Rva)) {
    return false;
  }

  return true;
}

}  // namespace crashpad
