/*
 * Copyright (C) 2017 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.
 */

#define ATRACE_TAG ATRACE_TAG_RESOURCES

#include "androidfw/Idmap.h"

#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
#include "androidfw/misc.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"

#ifdef _WIN32
#ifdef ERROR
#undef ERROR
#endif
#endif

using ::android::base::StringPrintf;

namespace android {

// See frameworks/base/cmds/idmap2/include/idmap2/Idmap.h for full idmap file format specification.
struct Idmap_header {
  // Always 0x504D4449 ('IDMP')
  uint32_t magic;
  uint32_t version;

  uint32_t target_crc32;
  uint32_t overlay_crc32;

  uint32_t fulfilled_policies;
  uint32_t enforce_overlayable;

  // overlay_path, target_path, and other string values encoded in the idmap header and read and
  // stored in separate structures. This allows the idmap header data to be casted to this struct
  // without having to read/store each header entry separately.
};

struct Idmap_data_header {
  uint32_t target_entry_count;
  uint32_t target_inline_entry_count;
  uint32_t target_inline_entry_value_count;
  uint32_t configuration_count;
  uint32_t overlay_entry_count;

  uint32_t string_pool_index_offset;
};

struct Idmap_target_entry {
  uint32_t target_id;
  uint32_t overlay_id;
};

struct Idmap_target_entry_inline {
  uint32_t target_id;
  uint32_t start_value_index;
  uint32_t value_count;
};

struct Idmap_target_entry_inline_value {
  uint32_t config_index;
  Res_value value;
};

struct Idmap_overlay_entry {
  uint32_t overlay_id;
  uint32_t target_id;
};

OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
    : data_header_(loaded_idmap->data_header_),
      idmap_string_pool_(loaded_idmap->string_pool_.get()) { };

OverlayStringPool::~OverlayStringPool() {
  uninit();
}

base::expected<StringPiece16, NullOrIOError> OverlayStringPool::stringAt(size_t idx) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
    return idmap_string_pool_->stringAt(idx - offset);
  }

  return ResStringPool::stringAt(idx);
}

base::expected<StringPiece, NullOrIOError> OverlayStringPool::string8At(size_t idx) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
    return idmap_string_pool_->string8At(idx - offset);
  }

  return ResStringPool::string8At(idx);
}

size_t OverlayStringPool::size() const {
  return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
}

OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
                                               const Idmap_overlay_entry* entries,
                                               uint8_t target_assigned_package_id)
    : data_header_(data_header),
      entries_(entries),
      target_assigned_package_id_(target_assigned_package_id) {}

status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
  const Idmap_overlay_entry* first_entry = entries_;
  const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
  auto entry = std::lower_bound(first_entry, end_entry, *resId,
                                [](const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
    return dtohl(e1.overlay_id) < overlay_id;
  });

  if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
    // A mapping for the target resource id could not be found.
    return DynamicRefTable::lookupResourceId(resId);
  }

  *resId = (0x00FFFFFFU & dtohl(entry->target_id))
      | (((uint32_t) target_assigned_package_id_) << 24U);
  return NO_ERROR;
}

status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) const {
  return DynamicRefTable::lookupResourceId(resId);
}

IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
                         const Idmap_target_entry* entries,
                         const Idmap_target_entry_inline* inline_entries,
                         const Idmap_target_entry_inline_value* inline_entry_values,
                         const ConfigDescription* configs,
                         uint8_t target_assigned_package_id,
                         const OverlayDynamicRefTable* overlay_ref_table)
    : data_header_(data_header),
      entries_(entries),
      inline_entries_(inline_entries),
      inline_entry_values_(inline_entry_values),
      configurations_(configs),
      target_assigned_package_id_(target_assigned_package_id),
      overlay_ref_table_(overlay_ref_table) { }

IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
  if ((target_res_id >> 24U) != target_assigned_package_id_) {
    // The resource id must have the same package id as the target package.
    return {};
  }

  // The resource ids encoded within the idmap are build-time resource ids so do not consider the
  // package id when determining if the resource in the target package is overlaid.
  target_res_id &= 0x00FFFFFFU;

  // Check if the target resource is mapped to an overlay resource.
  auto first_entry = entries_;
  auto end_entry = entries_ + dtohl(data_header_->target_entry_count);
  auto entry = std::lower_bound(first_entry, end_entry, target_res_id,
                                [](const Idmap_target_entry& e, const uint32_t target_id) {
    return (0x00FFFFFFU & dtohl(e.target_id)) < target_id;
  });

  if (entry != end_entry && (0x00FFFFFFU & dtohl(entry->target_id)) == target_res_id) {
    uint32_t overlay_resource_id = dtohl(entry->overlay_id);
    // Lookup the resource without rewriting the overlay resource id back to the target resource id
    // being looked up.
    overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
    return Result(overlay_resource_id);
  }

  // Check if the target resources is mapped to an inline table entry.
  auto first_inline_entry = inline_entries_;
  auto end_inline_entry = inline_entries_ + dtohl(data_header_->target_inline_entry_count);
  auto inline_entry = std::lower_bound(first_inline_entry, end_inline_entry, target_res_id,
                                       [](const Idmap_target_entry_inline& e,
                                          const uint32_t target_id) {
    return (0x00FFFFFFU & dtohl(e.target_id)) < target_id;
  });

  if (inline_entry != end_inline_entry &&
      (0x00FFFFFFU & dtohl(inline_entry->target_id)) == target_res_id) {
    std::map<ConfigDescription, Res_value> values_map;
    for (int i = 0; i < inline_entry->value_count; i++) {
      const auto& value = inline_entry_values_[inline_entry->start_value_index + i];
      const auto& config = configurations_[value.config_index];
      values_map[config] = value.value;
    }
    return Result(std::move(values_map));
  }
  return {};
}

namespace {
template <typename T>
const T* ReadType(const uint8_t** in_out_data_ptr, size_t* in_out_size, const std::string& label,
                  size_t count = 1) {
  if (!util::IsFourByteAligned(*in_out_data_ptr)) {
    LOG(ERROR) << "Idmap " << label << " is not word aligned.";
    return {};
  }
  if ((*in_out_size / sizeof(T)) < count) {
    LOG(ERROR) << "Idmap too small for the number of " << label << " entries ("
               << count << ").";
    return nullptr;
  }
  auto data_ptr = *in_out_data_ptr;
  const size_t read_size = sizeof(T) * count;
  *in_out_data_ptr += read_size;
  *in_out_size -= read_size;
  return reinterpret_cast<const T*>(data_ptr);
}

std::optional<std::string_view> ReadString(const uint8_t** in_out_data_ptr, size_t* in_out_size,
                                           const std::string& label) {
  const auto* len = ReadType<uint32_t>(in_out_data_ptr, in_out_size, label + " length");
  if (len == nullptr) {
    return {};
  }
  const auto* data = ReadType<char>(in_out_data_ptr, in_out_size, label, *len);
  if (data == nullptr) {
    return {};
  }
  // Strings are padded to the next 4 byte boundary.
  const uint32_t padding_size = (4U - ((size_t)*in_out_data_ptr & 0x3U)) % 4U;
  for (uint32_t i = 0; i < padding_size; i++) {
    if (**in_out_data_ptr != 0) {
      LOG(ERROR) << " Idmap padding of " << label << " is non-zero.";
      return {};
    }
    *in_out_data_ptr += sizeof(uint8_t);
    *in_out_size -= sizeof(uint8_t);
  }
  return std::string_view(data, *len);
}
} // namespace

// O_PATH is a lightweight way of creating an FD, only exists on Linux
#ifndef O_PATH
#define O_PATH (0)
#endif

LoadedIdmap::LoadedIdmap(const std::string& idmap_path, const Idmap_header* header,
                         const Idmap_data_header* data_header,
                         const Idmap_target_entry* target_entries,
                         const Idmap_target_entry_inline* target_inline_entries,
                         const Idmap_target_entry_inline_value* inline_entry_values,
                         const ConfigDescription* configs,
                         const Idmap_overlay_entry* overlay_entries,
                         std::unique_ptr<ResStringPool>&& string_pool,
                         std::string_view overlay_apk_path, std::string_view target_apk_path)
    : header_(header),
      data_header_(data_header),
      target_entries_(target_entries),
      target_inline_entries_(target_inline_entries),
      inline_entry_values_(inline_entry_values),
      configurations_(configs),
      overlay_entries_(overlay_entries),
      string_pool_(std::move(string_pool)),
      idmap_fd_(android::base::utf8::open(idmap_path.c_str(), O_RDONLY|O_CLOEXEC|O_BINARY|O_PATH)),
      overlay_apk_path_(overlay_apk_path),
      target_apk_path_(target_apk_path),
      idmap_last_mod_time_(getFileModDate(idmap_fd_.get())) {}

std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPiece idmap_data) {
  ATRACE_CALL();
  size_t data_size = idmap_data.size();
  auto data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data());

  // Parse the idmap header
  auto header = ReadType<Idmap_header>(&data_ptr, &data_size, "header");
  if (header == nullptr) {
    return {};
  }
  if (dtohl(header->magic) != kIdmapMagic) {
    LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
                               dtohl(header->magic), kIdmapMagic);
    return {};
  }
  if (dtohl(header->version) != kIdmapCurrentVersion) {
    // We are strict about versions because files with this format are generated at runtime and
    // don't need backwards compatibility.
    LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)",
                               dtohl(header->version), kIdmapCurrentVersion);
    return {};
  }
  std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
    if (!target_path) {
      return {};
    }
  std::optional<std::string_view> overlay_path = ReadString(&data_ptr, &data_size, "overlay path");
  if (!overlay_path) {
    return {};
  }
  if (!ReadString(&data_ptr, &data_size, "target name") ||
      !ReadString(&data_ptr, &data_size, "debug info")) {
    return {};
  }

  // Parse the idmap data blocks. Currently idmap2 can only generate one data block.
  auto data_header = ReadType<Idmap_data_header>(&data_ptr, &data_size, "data header");
  if (data_header == nullptr) {
    return {};
  }
  auto target_entries = ReadType<Idmap_target_entry>(&data_ptr, &data_size, "target",
                                                     dtohl(data_header->target_entry_count));
  if (target_entries == nullptr) {
    return {};
  }
  auto target_inline_entries = ReadType<Idmap_target_entry_inline>(
      &data_ptr, &data_size, "target inline", dtohl(data_header->target_inline_entry_count));
  if (target_inline_entries == nullptr) {
    return {};
  }

  auto target_inline_entry_values = ReadType<Idmap_target_entry_inline_value>(
      &data_ptr, &data_size, "target inline values",
      dtohl(data_header->target_inline_entry_value_count));
  if (target_inline_entry_values == nullptr) {
    return {};
  }

  auto configurations = ReadType<ConfigDescription>(
      &data_ptr, &data_size, "configurations",
      dtohl(data_header->configuration_count));
  if (configurations == nullptr) {
    return {};
  }

  auto overlay_entries = ReadType<Idmap_overlay_entry>(&data_ptr, &data_size, "target inline",
                                                       dtohl(data_header->overlay_entry_count));
  if (overlay_entries == nullptr) {
    return {};
  }
  std::optional<std::string_view> string_pool = ReadString(&data_ptr, &data_size, "string pool");
  if (!string_pool) {
    return {};
  }
  auto idmap_string_pool = util::make_unique<ResStringPool>();
  if (!string_pool->empty()) {
    const status_t err = idmap_string_pool->setTo(string_pool->data(), string_pool->size());
    if (err != NO_ERROR) {
      LOG(ERROR) << "idmap string pool corrupt.";
      return {};
    }
  }

  if (data_size != 0) {
    LOG(ERROR) << "idmap parsed with " << data_size << "bytes remaining";
    return {};
  }

  // Can't use make_unique because LoadedIdmap constructor is private.
  return std::unique_ptr<LoadedIdmap>(
      new LoadedIdmap(std::string(idmap_path), header, data_header, target_entries,
                      target_inline_entries, target_inline_entry_values, configurations,
                      overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
}

bool LoadedIdmap::IsUpToDate() const {
  return idmap_last_mod_time_ == getFileModDate(idmap_fd_.get());
}

}  // namespace android
