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

#include "art_method-inl.h"
#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
#include "mirror/class-inl.h"

namespace art HIDDEN {

SdkChecker::SdkChecker() : enabled_(true) {}

SdkChecker* SdkChecker::Create(const std::string& public_sdk, std::string* error_msg) {
  std::vector<std::string> dex_file_paths;
  Split(public_sdk, ':', &dex_file_paths);

  std::unique_ptr<SdkChecker> sdk_checker(new SdkChecker());
  for (const std::string& path : dex_file_paths) {
    DexFileLoader dex_file_loader(path);
    if (!dex_file_loader.Open(/*verify=*/true,
                              /*verify_checksum*/ false,
                              error_msg,
                              &sdk_checker->sdk_dex_files_)) {
      return nullptr;
    }
  }
  return sdk_checker.release();
}

bool SdkChecker::ShouldDenyAccess(ArtMethod* art_method) const {
  if (!enabled_) {
    return false;
  }

  bool found = false;
  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
    const dex::TypeId* declaring_type_id =
        dex_file->FindTypeId(art_method->GetDeclaringClassDescriptor());
    if (declaring_type_id == nullptr) {
      continue;
    }
    const dex::StringId* name_id = dex_file->FindStringId(art_method->GetName());
    if (name_id == nullptr) {
      continue;
    }

    dex::TypeIndex return_type_idx;
    std::vector<dex::TypeIndex> param_type_idxs;
    if (!dex_file->CreateTypeList(
            art_method->GetSignature().ToString(), &return_type_idx, &param_type_idxs)) {
      continue;
    }
    const dex::ProtoId* proto_id = dex_file->FindProtoId(return_type_idx, param_type_idxs);
    if (proto_id == nullptr) {
      continue;
    }

    const dex::MethodId* method_id =
        dex_file->FindMethodId(*declaring_type_id, *name_id, *proto_id);
    if (method_id != nullptr) {
      found = true;
      break;
    }
  }

  if (!found) {
    VLOG(verifier) << "Deny for " << art_method->PrettyMethod(true);
  }

  // Deny access if we didn't find the descriptor in the public api dex files.
  return !found;
}

bool SdkChecker::ShouldDenyAccess(ArtField* art_field) const {
  if (!enabled_) {
    return false;
  }

  bool found = false;
  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
    std::string declaring_class;

    const dex::TypeId* declaring_type_id =
        dex_file->FindTypeId(art_field->GetDeclaringClass()->GetDescriptor(&declaring_class));
    if (declaring_type_id == nullptr) {
      continue;
    }
    const dex::StringId* name_id = dex_file->FindStringId(art_field->GetName());
    if (name_id == nullptr) {
      continue;
    }
    const dex::TypeId* type_id = dex_file->FindTypeId(art_field->GetTypeDescriptor());
    if (type_id == nullptr) {
      continue;
    }

    const dex::FieldId* field_id = dex_file->FindFieldId(*declaring_type_id, *name_id, *type_id);
    if (field_id != nullptr) {
      found = true;
      break;
    }
  }

  if (!found) {
    VLOG(verifier) << "Deny for " << ArtField::PrettyField(art_field, true);
  }

  // Deny access if we didn't find the descriptor in the public api dex files.
  return !found;
}

bool SdkChecker::ShouldDenyAccess(const char* descriptor) const {
  if (!enabled_) {
    return false;
  }

  bool found = false;
  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
    const dex::TypeId* type_id = dex_file->FindTypeId(descriptor);
    if (type_id != nullptr) {
      dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
      if (dex_file->FindClassDef(type_idx) != nullptr) {
        found = true;
        break;
      }
    }
  }

  if (!found) {
    VLOG(verifier) << "Deny for " << descriptor;
  }

  // Deny access if we didn't find the descriptor in the public api dex files.
  return !found;
}

}  // namespace art
