/*
 * 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 boot, as the app
  // might define blocked APIs (which won't be used at runtime).
  const auto& name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
  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 boot, as the app
  // might define blocked APIs (which won't be used at runtime).
  const auto& name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
  field_locations_[name].push_back(ref);
}

void HiddenApiFinder::CollectAccesses(VeridexResolver* resolver,
                                      const ClassFilter& class_filter) {
  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)));
    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()) {
    if (class_filter.Matches(accessor.GetDescriptor())) {
      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
        CodeItemInstructionAccessor codes = method.GetInstructions();
        const uint32_t max_pc = codes.InsnsSizeInCodeUnits();
        for (const DexInstructionPcPair& inst : codes) {
          if (inst.DexPc() >= max_pc) {
            // We need to prevent abnormal access for outside of code
            break;
          }

          switch (inst->Opcode()) {
            case Instruction::CONST_STRING: {
              dex::StringIndex string_index(inst->VRegB_21c());
              const auto& 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_.IsInBoot(str)) {
                  classes_.insert(str);
                } else if (hidden_api_.IsInBoot(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,
                          const ClassFilter& class_filter) {
  for (const std::unique_ptr<VeridexResolver>& resolver : resolvers) {
    CollectAccesses(resolver.get(), class_filter);
  }
}

void HiddenApiFinder::Dump(std::ostream& os,
                           HiddenApiStats* stats,
                           bool dump_reflection) {
  // Dump methods from hidden APIs linked against.
  for (const std::pair<const std::string,
                       std::vector<MethodReference>>& pair : method_locations_) {
    const auto& name = pair.first;
    if (hidden_api_.GetSignatureSource(name) != SignatureSource::APP &&
        hidden_api_.ShouldReport(name)) {
      stats->linking_count++;
      hiddenapi::ApiList api_list = hidden_api_.GetApiList(pair.first);
      stats->api_counts[api_list.GetIntValue()]++;
      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_) {
    const auto& name = pair.first;
    if (hidden_api_.GetSignatureSource(name) != SignatureSource::APP &&
        hidden_api_.ShouldReport(name)) {
      stats->linking_count++;
      hiddenapi::ApiList api_list = hidden_api_.GetApiList(pair.first);
      stats->api_counts[api_list.GetIntValue()]++;
      // Note: There is a test depending on this output format,
      // so please be careful when you modify the format. b/123662832
      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;
        if (hidden_api_.GetSignatureSource(full_name) != SignatureSource::APP &&
            hidden_api_.ShouldReport(full_name)) {
          hiddenapi::ApiList api_list = hidden_api_.GetApiList(full_name);
          stats->api_counts[api_list.GetIntValue()]++;
          stats->reflection_count++;
          // Note: There is a test depending on this output format,
          // so please be careful when you modify the format. b/123662832
          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
