/*
 * Copyright (C) 2018 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 "hidden_api_finder.h"

#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_instruction-inl.h"
#include "dex/dex_file.h"
#include "dex/method_reference.h"
#include "hidden_api.h"
#include "resolver.h"
#include "veridex.h"

#include <iostream>

namespace art {

void HiddenApiFinder::CheckMethod(uint32_t method_id,
                                  VeridexResolver* resolver,
                                  MethodReference ref) {
  // Note: we always query whether a method is in a list, as the app
  // might define blacklisted APIs (which won't be used at runtime).
  std::string name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
  if (hidden_api_.IsInAnyList(name)) {
    method_locations_[name].push_back(ref);
  }
}

void HiddenApiFinder::CheckField(uint32_t field_id,
                                 VeridexResolver* resolver,
                                 MethodReference ref) {
  // Note: we always query whether a field is in a list, as the app
  // might define blacklisted APIs (which won't be used at runtime).
  std::string name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
  if (hidden_api_.IsInAnyList(name)) {
    field_locations_[name].push_back(ref);
  }
}

void HiddenApiFinder::CollectAccesses(VeridexResolver* resolver) {
  const DexFile& dex_file = resolver->GetDexFile();
  // Look at all types referenced in this dex file. Any of these
  // types can lead to being used through reflection.
  for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
    std::string name(dex_file.StringByTypeIdx(dex::TypeIndex(i)));
    if (hidden_api_.IsInAnyList(name)) {
      classes_.insert(name);
    }
  }
  // Note: we collect strings constants only referenced in code items as the string table
  // contains other kind of strings (eg types).
  for (ClassAccessor accessor : dex_file.GetClasses()) {
    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
      for (const DexInstructionPcPair& inst : method.GetInstructions()) {
        switch (inst->Opcode()) {
          case Instruction::CONST_STRING: {
            dex::StringIndex string_index(inst->VRegB_21c());
            std::string name = std::string(dex_file.StringDataByIdx(string_index));
            // Cheap filtering on the string literal. We know it cannot be a field/method/class
            // if it contains a space.
            if (name.find(' ') == std::string::npos) {
              // Class names at the Java level are of the form x.y.z, but the list encodes
              // them of the form Lx/y/z;. Inner classes have '$' for both Java level class
              // names in strings, and hidden API lists.
              std::string str = HiddenApi::ToInternalName(name);
              // Note: we can query the lists directly, as HiddenApi added classes that own
              // private methods and fields in them.
              // We don't add class names to the `strings_` set as we know method/field names
              // don't have '.' or '/'. All hidden API class names have a '/'.
              if (hidden_api_.IsInAnyList(str)) {
                classes_.insert(str);
              } else if (hidden_api_.IsInAnyList(name)) {
                // Could be something passed to JNI.
                classes_.insert(name);
              } else {
                // We only keep track of the location for strings, as these will be the
                // field/method names the user is interested in.
                strings_.insert(name);
                reflection_locations_[name].push_back(method.GetReference());
              }
            }
            break;
          }
          case Instruction::INVOKE_DIRECT:
          case Instruction::INVOKE_INTERFACE:
          case Instruction::INVOKE_STATIC:
          case Instruction::INVOKE_SUPER:
          case Instruction::INVOKE_VIRTUAL: {
            CheckMethod(inst->VRegB_35c(), resolver, method.GetReference());
            break;
          }

          case Instruction::INVOKE_DIRECT_RANGE:
          case Instruction::INVOKE_INTERFACE_RANGE:
          case Instruction::INVOKE_STATIC_RANGE:
          case Instruction::INVOKE_SUPER_RANGE:
          case Instruction::INVOKE_VIRTUAL_RANGE: {
            CheckMethod(inst->VRegB_3rc(), resolver, method.GetReference());
            break;
          }

          case Instruction::IGET:
          case Instruction::IGET_WIDE:
          case Instruction::IGET_OBJECT:
          case Instruction::IGET_BOOLEAN:
          case Instruction::IGET_BYTE:
          case Instruction::IGET_CHAR:
          case Instruction::IGET_SHORT: {
            CheckField(inst->VRegC_22c(), resolver, method.GetReference());
            break;
          }

          case Instruction::IPUT:
          case Instruction::IPUT_WIDE:
          case Instruction::IPUT_OBJECT:
          case Instruction::IPUT_BOOLEAN:
          case Instruction::IPUT_BYTE:
          case Instruction::IPUT_CHAR:
          case Instruction::IPUT_SHORT: {
            CheckField(inst->VRegC_22c(), resolver, method.GetReference());
            break;
          }

          case Instruction::SGET:
          case Instruction::SGET_WIDE:
          case Instruction::SGET_OBJECT:
          case Instruction::SGET_BOOLEAN:
          case Instruction::SGET_BYTE:
          case Instruction::SGET_CHAR:
          case Instruction::SGET_SHORT: {
            CheckField(inst->VRegB_21c(), resolver, method.GetReference());
            break;
          }

          case Instruction::SPUT:
          case Instruction::SPUT_WIDE:
          case Instruction::SPUT_OBJECT:
          case Instruction::SPUT_BOOLEAN:
          case Instruction::SPUT_BYTE:
          case Instruction::SPUT_CHAR:
          case Instruction::SPUT_SHORT: {
            CheckField(inst->VRegB_21c(), resolver, method.GetReference());
            break;
          }

          default:
            break;
        }
      }
    }
  }
}

void HiddenApiFinder::Run(const std::vector<std::unique_ptr<VeridexResolver>>& resolvers) {
  for (const std::unique_ptr<VeridexResolver>& resolver : resolvers) {
    CollectAccesses(resolver.get());
  }
}

void HiddenApiFinder::Dump(std::ostream& os,
                           HiddenApiStats* stats,
                           bool dump_reflection) {
  stats->linking_count = method_locations_.size() + field_locations_.size();

  // Dump methods from hidden APIs linked against.
  for (const std::pair<const std::string,
                       std::vector<MethodReference>>& pair : method_locations_) {
    HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(pair.first);
    stats->api_counts[api_list]++;
    os << "#" << ++stats->count << ": Linking " << api_list << " " << pair.first << " use(s):";
    os << std::endl;
    HiddenApiFinder::DumpReferences(os, pair.second);
    os << std::endl;
  }

  // Dump fields from hidden APIs linked against.
  for (const std::pair<const std::string,
                       std::vector<MethodReference>>& pair : field_locations_) {
    HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(pair.first);
    stats->api_counts[api_list]++;
    os << "#" << ++stats->count << ": Linking " << api_list << " " << pair.first << " use(s):";
    os << std::endl;
    HiddenApiFinder::DumpReferences(os, pair.second);
    os << std::endl;
  }

  if (dump_reflection) {
    // Dump potential reflection uses.
    for (const std::string& cls : classes_) {
      for (const std::string& name : strings_) {
        std::string full_name = cls + "->" + name;
        HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
        stats->api_counts[api_list]++;
        if (api_list != HiddenApiAccessFlags::kNoList) {
          stats->reflection_count++;
          os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name
             << " potential use(s):";
          os << std::endl;
          HiddenApiFinder::DumpReferences(os, reflection_locations_[name]);
          os << std::endl;
        }
      }
    }
  }
}

void HiddenApiFinder::DumpReferences(std::ostream& os,
                                     const std::vector<MethodReference>& references) {
  static const char* kPrefix = "       ";

  // Count number of occurrences of each reference, to make the output clearer.
  std::map<std::string, size_t> counts;
  for (const MethodReference& ref : references) {
    std::string ref_string = HiddenApi::GetApiMethodName(ref);
    if (!counts.count(ref_string)) {
      counts[ref_string] = 0;
    }
    counts[ref_string]++;
  }

  for (const std::pair<const std::string, size_t>& pair : counts) {
    os << kPrefix << pair.first;
    if (pair.second > 1) {
       os << " (" << pair.second << " occurrences)";
    }
    os << std::endl;
  }
}

}  // namespace art
