/*
 * 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/logging.h"
#include "android-base/stringprintf.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 {

static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
  return dtohl(e1.target_id) < target_id;
}

static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
  return dtohl(e1.overlay_id) < overlay_id;
}

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

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

const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
    return idmap_string_pool_->stringAt(idx - offset, outLen);
  }

  return ResStringPool::stringAt(idx, outLen);
}

const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
    return idmap_string_pool_->string8At(idx - offset, outLen);
  }

  return ResStringPool::string8At(idx, outLen);
}

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, compare_overlay_entries);

  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_) << 24);
  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,
                         uint8_t target_assigned_package_id,
                         const OverlayDynamicRefTable* overlay_ref_table)
    : data_header_(data_header),
      entries_(entries),
      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 >> 24) != 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.
  target_res_id = (0x00FFFFFFU & target_res_id)
      | (((uint32_t) data_header_->target_package_id) << 24);

  const Idmap_target_entry* first_entry = entries_;
  const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
  auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);

  if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
    // A mapping for the target resource id could not be found.
    return {};
  }

  // A reference should be treated as an alias of the resource. Instead of returning the table
  // entry, return the alias resource id to look up. The alias resource might not reside within the
  // overlay package, so the resource id must be fixed with the dynamic reference table of the
  // overlay before returning.
  if (entry->type == Res_value::TYPE_REFERENCE
      || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
    uint32_t overlay_resource_id = dtohl(entry->value);

    // 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);
  }

  // Copy the type and value into the ResTable_entry structure needed by asset manager.
  uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
  auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
  memset(table_entry, 0, malloc_size);
  table_entry->size = htods(sizeof(ResTable_entry));

  auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
      + sizeof(ResTable_entry));
  table_value->dataType = entry->type;
  table_value->data = entry->value;

  return Result(ResTable_entry_handle::managed(table_entry));
}

static bool is_word_aligned(const void* data) {
  return (reinterpret_cast<uintptr_t>(data) & 0x03) == 0;
}

static bool IsValidIdmapHeader(const StringPiece& data) {
  if (!is_word_aligned(data.data())) {
    LOG(ERROR) << "Idmap header is not word aligned.";
    return false;
  }

  if (data.size() < sizeof(Idmap_header)) {
    LOG(ERROR) << "Idmap header is too small.";
    return false;
  }

  const Idmap_header* header = reinterpret_cast<const Idmap_header*>(data.data());
  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 false;
  }

  if (dtohl(header->version) != kIdmapCurrentVersion) {
    // We are strict about versions because files with this format are auto-generated and don't need
    // backwards compatibility.
    LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)",
                               dtohl(header->version), kIdmapCurrentVersion);
    return false;
  }

  return true;
}

LoadedIdmap::LoadedIdmap(const Idmap_header* header,
                         const Idmap_data_header* data_header,
                         const Idmap_target_entry* target_entries,
                         const Idmap_overlay_entry* overlay_entries,
                         ResStringPool* string_pool)
     : header_(header),
       data_header_(data_header),
       target_entries_(target_entries),
       overlay_entries_(overlay_entries),
       string_pool_(string_pool) {

  size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
                          arraysize(header_->overlay_path));
  overlay_apk_path_.assign(reinterpret_cast<const char*>(header_->overlay_path), length);

  length = strnlen(reinterpret_cast<const char*>(header_->target_path),
                          arraysize(header_->target_path));
  target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);
}

std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
  ATRACE_CALL();
  if (!IsValidIdmapHeader(idmap_data)) {
    return {};
  }

  auto header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + sizeof(*header);
  size_t data_size = idmap_data.size() - sizeof(*header);

  // Currently idmap2 can only generate one data block.
  auto data_header = reinterpret_cast<const Idmap_data_header*>(data_ptr);
  data_ptr += sizeof(*data_header);
  data_size -= sizeof(*data_header);

  // Make sure there is enough space for the target entries declared in the header.
  const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
  if (data_size / sizeof(Idmap_target_entry) <
      static_cast<size_t>(dtohl(data_header->target_entry_count))) {
    LOG(ERROR) << StringPrintf("Idmap too small for the number of target entries (%d)",
                               (int)dtohl(data_header->target_entry_count));
    return {};
  }

  // Advance the data pointer past the target entries.
  const size_t target_entry_size_bytes =
      (dtohl(data_header->target_entry_count) * sizeof(Idmap_target_entry));
  data_ptr += target_entry_size_bytes;
  data_size -= target_entry_size_bytes;

  // Make sure there is enough space for the overlay entries declared in the header.
  const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
  if (data_size / sizeof(Idmap_overlay_entry) <
      static_cast<size_t>(dtohl(data_header->overlay_entry_count))) {
    LOG(ERROR) << StringPrintf("Idmap too small for the number of overlay entries (%d)",
                               (int)dtohl(data_header->overlay_entry_count));
    return {};
  }

  // Advance the data pointer past the target entries.
  const size_t overlay_entry_size_bytes =
      (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
  data_ptr += overlay_entry_size_bytes;
  data_size -= overlay_entry_size_bytes;

  // Read the idmap string pool that holds the value of inline string entries.
  if (data_size < dtohl(data_header->string_pool_length)) {
    LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
                               (int)dtohl(data_header->string_pool_length));
    return {};
  }

  auto idmap_string_pool = util::make_unique<ResStringPool>();
  if (dtohl(data_header->string_pool_length) > 0) {
    status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
    if (err != NO_ERROR) {
      LOG(ERROR) << "idmap string pool corrupt.";
      return {};
    }
  }

  // Can't use make_unique because LoadedIdmap constructor is private.
  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
                      idmap_string_pool.release()));

  return std::move(loaded_idmap);
}

}  // namespace android
