/*
 * 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 blacklisted 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 blacklisted 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
