// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// 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/win/pe_image_reader.h"

#include <stddef.h>
#include <string.h>

#include <algorithm>
#include <memory>

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "client/crashpad_info.h"
#include "snapshot/win/pe_image_resource_reader.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/pdb_structures.h"
#include "util/win/process_structs.h"

namespace crashpad {

namespace {

// Map from Traits to an IMAGE_NT_HEADERSxx.
template <class Traits>
struct NtHeadersForTraits;

template <>
struct NtHeadersForTraits<process_types::internal::Traits32> {
  using type = IMAGE_NT_HEADERS32;
};

template <>
struct NtHeadersForTraits<process_types::internal::Traits64> {
  using type = IMAGE_NT_HEADERS64;
};

}  // namespace

PEImageReader::PEImageReader()
    : module_subrange_reader_(),
      initialized_() {
}

PEImageReader::~PEImageReader() {
}

bool PEImageReader::Initialize(ProcessReaderWin* process_reader,
                               WinVMAddress address,
                               WinVMSize size,
                               const std::string& module_name) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  if (!module_subrange_reader_.Initialize(
          process_reader, address, size, module_name)) {
    return false;
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

bool PEImageReader::GetCrashpadInfoSection(WinVMAddress* address,
                                           WinVMSize* size) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  if (module_subrange_reader_.Is64Bit()) {
    return GetCrashpadInfoSectionInternal<process_types::internal::Traits64>(
        address, size);
  } else {
    return GetCrashpadInfoSectionInternal<process_types::internal::Traits32>(
        address, size);
  }
}

template <class Traits>
bool PEImageReader::GetCrashpadInfo(
    process_types::CrashpadInfo<Traits>* crashpad_info) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  IMAGE_SECTION_HEADER section;
  if (!GetSectionByName<typename NtHeadersForTraits<Traits>::type>("CPADinfo",
                                                                   &section)) {
    return false;
  }

  if (section.Misc.VirtualSize <
      offsetof(process_types::CrashpadInfo<Traits>, size) +
          sizeof(crashpad_info->size)) {
    LOG(WARNING) << "small crashpad info section size "
                 << section.Misc.VirtualSize << ", "
                 << module_subrange_reader_.name();
    return false;
  }

  const WinVMAddress crashpad_info_address = Address() + section.VirtualAddress;
  const WinVMSize crashpad_info_size =
      std::min(static_cast<WinVMSize>(sizeof(*crashpad_info)),
               static_cast<WinVMSize>(section.Misc.VirtualSize));
  if (!module_subrange_reader_.ReadMemory(
          crashpad_info_address, crashpad_info_size, crashpad_info)) {
    LOG(WARNING) << "could not read crashpad info from "
                 << module_subrange_reader_.name();
    return false;
  }

  if (crashpad_info->size < sizeof(*crashpad_info)) {
    // Zero out anything beyond the structure’s declared size.
    memset(reinterpret_cast<char*>(crashpad_info) + crashpad_info->size,
           0,
           sizeof(*crashpad_info) - crashpad_info->size);
  }

  if (crashpad_info->signature != CrashpadInfo::kSignature ||
      crashpad_info->version != 1) {
    LOG(WARNING) << base::StringPrintf(
        "unexpected crashpad info signature 0x%x, version %u in %s",
        crashpad_info->signature,
        crashpad_info->version,
        module_subrange_reader_.name().c_str());
    return false;
  }

  // Don’t require strict equality, to leave wiggle room for sloppy linkers.
  if (crashpad_info->size > section.Misc.VirtualSize) {
    LOG(WARNING) << "crashpad info struct size " << crashpad_info->size
                 << " large for section size " << section.Misc.VirtualSize
                 << " in " << module_subrange_reader_.name();
    return false;
  }

  if (crashpad_info->size > sizeof(*crashpad_info)) {
    // This isn’t strictly a problem, because unknown fields will simply be
    // ignored, but it may be of diagnostic interest.
    LOG(INFO) << "large crashpad info size " << crashpad_info->size << ", "
              << module_subrange_reader_.name();
  }

  return true;
}

bool PEImageReader::DebugDirectoryInformation(UUID* uuid,
                                              DWORD* age,
                                              std::string* pdbname) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  IMAGE_DATA_DIRECTORY data_directory;
  if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, &data_directory))
    return false;

  IMAGE_DEBUG_DIRECTORY debug_directory;
  if (data_directory.Size % sizeof(debug_directory) != 0)
    return false;
  for (size_t offset = 0; offset < data_directory.Size;
       offset += sizeof(debug_directory)) {
    if (!module_subrange_reader_.ReadMemory(
            Address() + data_directory.VirtualAddress + offset,
            sizeof(debug_directory),
            &debug_directory)) {
      LOG(WARNING) << "could not read data directory from "
                   << module_subrange_reader_.name();
      return false;
    }

    if (debug_directory.Type != IMAGE_DEBUG_TYPE_CODEVIEW)
      continue;

    if (debug_directory.AddressOfRawData) {
      if (debug_directory.SizeOfData < sizeof(CodeViewRecordPDB70)) {
        LOG(WARNING) << "CodeView debug entry of unexpected size in "
                     << module_subrange_reader_.name();
        continue;
      }

      std::unique_ptr<char[]> data(new char[debug_directory.SizeOfData]);
      if (!module_subrange_reader_.ReadMemory(
              Address() + debug_directory.AddressOfRawData,
              debug_directory.SizeOfData,
              data.get())) {
        LOG(WARNING) << "could not read debug directory from "
                     << module_subrange_reader_.name();
        return false;
      }

      if (*reinterpret_cast<DWORD*>(data.get()) !=
          CodeViewRecordPDB70::kSignature) {
        LOG(WARNING) << "encountered non-7.0 CodeView debug record in "
                     << module_subrange_reader_.name();
        continue;
      }

      CodeViewRecordPDB70* codeview =
          reinterpret_cast<CodeViewRecordPDB70*>(data.get());
      *uuid = codeview->uuid;
      *age = codeview->age;
      // This is a NUL-terminated string encoded in the codepage of the system
      // where the binary was linked. We have no idea what that was, so we just
      // assume ASCII.
      *pdbname = std::string(reinterpret_cast<char*>(&codeview->pdb_name[0]));
      return true;
    } else if (debug_directory.PointerToRawData) {
      // This occurs for non-PDB based debug information. We simply ignore these
      // as we don't expect to encounter modules that will be in this format
      // for which we'll actually have symbols. See
      // https://crashpad.chromium.org/bug/47.
    }
  }

  return false;
}

bool PEImageReader::VSFixedFileInfo(
    VS_FIXEDFILEINFO* vs_fixed_file_info) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  IMAGE_DATA_DIRECTORY data_directory;
  if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE,
                               &data_directory)) {
    return false;
  }

  PEImageResourceReader resource_reader;
  if (!resource_reader.Initialize(module_subrange_reader_, data_directory)) {
    return false;
  }

  WinVMAddress address;
  WinVMSize size;
  if (!resource_reader.FindResourceByID(
          FromPointerCast<uint16_t>(VS_FILE_INFO),  // RT_VERSION
          VS_VERSION_INFO,
          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
          &address,
          &size,
          nullptr)) {
    return false;
  }

  // This structure is not declared anywhere in the SDK, but is documented at
  // https://msdn.microsoft.com/library/ms647001.aspx.
  struct VS_VERSIONINFO {
    WORD wLength;
    WORD wValueLength;
    WORD wType;

    // The structure documentation on MSDN doesn’t show the [16], but it does
    // say that it’s supposed to be L"VS_VERSION_INFO", which is is in fact a
    // 16-character string (including its NUL terminator).
    WCHAR szKey[16];

    WORD Padding1;
    VS_FIXEDFILEINFO Value;

    // Don’t include Children or the Padding2 that precedes it, because they may
    // not be present.
    // WORD Padding2;
    // WORD Children;
  };
  VS_VERSIONINFO version_info;

  if (size < sizeof(version_info)) {
    LOG(WARNING) << "version info size " << size
                 << " too small for structure of size " << sizeof(version_info)
                 << " in " << module_subrange_reader_.name();
    return false;
  }

  if (!module_subrange_reader_.ReadMemory(
          address, sizeof(version_info), &version_info)) {
    LOG(WARNING) << "could not read version info from "
                 << module_subrange_reader_.name();
    return false;
  }

  if (version_info.wLength < sizeof(version_info) ||
      version_info.wValueLength != sizeof(version_info.Value) ||
      version_info.wType != 0 ||
      wcsncmp(version_info.szKey,
              L"VS_VERSION_INFO",
              base::size(version_info.szKey)) != 0) {
    LOG(WARNING) << "unexpected VS_VERSIONINFO in "
                 << module_subrange_reader_.name();
    return false;
  }

  if (version_info.Value.dwSignature != VS_FFI_SIGNATURE ||
      version_info.Value.dwStrucVersion != VS_FFI_STRUCVERSION) {
    LOG(WARNING) << "unexpected VS_FIXEDFILEINFO in "
                 << module_subrange_reader_.name();
    return false;
  }

  *vs_fixed_file_info = version_info.Value;
  vs_fixed_file_info->dwFileFlags &= vs_fixed_file_info->dwFileFlagsMask;
  return true;
}

template <class Traits>
bool PEImageReader::GetCrashpadInfoSectionInternal(WinVMAddress* address,
                                                   WinVMSize* size) const {
  IMAGE_SECTION_HEADER section;
  if (!GetSectionByName<typename NtHeadersForTraits<Traits>::type>("CPADinfo",
                                                                   &section)) {
    return false;
  }

  process_types::CrashpadInfo<Traits> crashpad_info;
  if (section.Misc.VirtualSize <
      offsetof(process_types::CrashpadInfo<Traits>, size) +
          sizeof(crashpad_info.size)) {
    LOG(WARNING) << "small crashpad info section size "
                 << section.Misc.VirtualSize << ", "
                 << module_subrange_reader_.name();
    return false;
  }

  *address = Address() + section.VirtualAddress;
  *size = std::min<WinVMSize>(sizeof(crashpad_info), section.Misc.VirtualSize);

  return true;
}

template <class NtHeadersType>
bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers,
                                  WinVMAddress* nt_headers_address) const {
  IMAGE_DOS_HEADER dos_header;
  if (!module_subrange_reader_.ReadMemory(
          Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) {
    LOG(WARNING) << "could not read dos header from "
                 << module_subrange_reader_.name();
    return false;
  }

  if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) {
    LOG(WARNING) << "invalid e_magic in dos header of "
                 << module_subrange_reader_.name();
    return false;
  }

  WinVMAddress local_nt_headers_address = Address() + dos_header.e_lfanew;
  if (!module_subrange_reader_.ReadMemory(
          local_nt_headers_address, sizeof(NtHeadersType), nt_headers)) {
    LOG(WARNING) << "could not read nt headers from "
                 << module_subrange_reader_.name();
    return false;
  }

  if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
    LOG(WARNING) << "invalid signature in nt headers of "
                 << module_subrange_reader_.name();
    return false;
  }

  if (nt_headers_address)
    *nt_headers_address = local_nt_headers_address;

  return true;
}

template <class NtHeadersType>
bool PEImageReader::GetSectionByName(const std::string& name,
                                     IMAGE_SECTION_HEADER* section) const {
  if (name.size() > sizeof(section->Name)) {
    LOG(WARNING) << "supplied section name too long " << name;
    return false;
  }

  NtHeadersType nt_headers;
  WinVMAddress nt_headers_address;
  if (!ReadNtHeaders(&nt_headers, &nt_headers_address))
    return false;

  WinVMAddress first_section_address =
      nt_headers_address + offsetof(NtHeadersType, OptionalHeader) +
      nt_headers.FileHeader.SizeOfOptionalHeader;
  for (DWORD i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) {
    WinVMAddress section_address =
        first_section_address + sizeof(IMAGE_SECTION_HEADER) * i;
    if (!module_subrange_reader_.ReadMemory(
            section_address, sizeof(IMAGE_SECTION_HEADER), section)) {
      LOG(WARNING) << "could not read section " << i << " from "
                   << module_subrange_reader_.name();
      return false;
    }
    if (strncmp(reinterpret_cast<const char*>(section->Name),
                name.c_str(),
                sizeof(section->Name)) == 0) {
      return true;
    }
  }

  return false;
}

bool PEImageReader::ImageDataDirectoryEntry(size_t index,
                                            IMAGE_DATA_DIRECTORY* entry) const {
  bool rv;
  if (module_subrange_reader_.Is64Bit()) {
    rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS64>(index, entry);
  } else {
    rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS32>(index, entry);
  }

  return rv && entry->VirtualAddress != 0 && entry->Size != 0;
}

template <class NtHeadersType>
bool PEImageReader::ImageDataDirectoryEntryT(
    size_t index,
    IMAGE_DATA_DIRECTORY* entry) const {
  NtHeadersType nt_headers;
  if (!ReadNtHeaders(&nt_headers, nullptr)) {
    return false;
  }

  if (nt_headers.FileHeader.SizeOfOptionalHeader <
          offsetof(decltype(nt_headers.OptionalHeader), DataDirectory[index]) +
              sizeof(nt_headers.OptionalHeader.DataDirectory[index]) ||
      nt_headers.OptionalHeader.NumberOfRvaAndSizes <= index) {
    return false;
  }

  *entry = nt_headers.OptionalHeader.DataDirectory[index];
  return true;
}

// Explicit instantiations with the only 2 valid template arguments to avoid
// putting the body of the function in the header.
template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits32>(
    process_types::CrashpadInfo<process_types::internal::Traits32>*
        crashpad_info) const;
template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits64>(
    process_types::CrashpadInfo<process_types::internal::Traits64>*
        crashpad_info) const;

}  // namespace crashpad
