diff --git a/source/model-generator/DFASourceGenerator.cpp b/source/model-generator/DFASourceGenerator.cpp new file mode 100644 index 00000000..c99e9df3 --- /dev/null +++ b/source/model-generator/DFASourceGenerator.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include + +namespace marianatrench { + +namespace { +bool is_class_accessible_via_dfa(const DexClass* clazz) { + if (!clazz->get_anno_set()) { + return false; + } + + auto dfa_annotation_type = + marianatrench::constants::get_dfa_annotation_type(); + for (const auto& annotation : clazz->get_anno_set()->get_annotations()) { + if (!annotation->type() || + annotation->type()->str() != dfa_annotation_type) { + continue; + } + + auto public_scope = marianatrench::constants::get_public_access_scope(); + for (const DexAnnotationElement& element : annotation->anno_elems()) { + if (element.string->str() == "enforceScope" && + element.encoded_value->as_value() == 0) { + return true; + } + + if (element.string->str() == "accessScope" && + element.encoded_value->show() == public_scope) { + return true; + } + } + } + return false; +} +} // namespace + +DFASourceGenerator::DFASourceGenerator(Context& context) + : ModelGenerator("dfa_source_generator", context) {} + +std::vector DFASourceGenerator::emit_method_models( + const Methods& methods) { + ConcurrentSet dfa_classes; + for (auto& scope : DexStoreClassesIterator(context_.stores)) { + walk::parallel::classes(scope, [&dfa_classes](DexClass* clazz) { + if (is_class_accessible_via_dfa(clazz)) { + dfa_classes.emplace(clazz); + } + }); + } + + ConcurrentSet nested_dfa_classes; + for (auto& scope : DexStoreClassesIterator(context_.stores)) { + walk::parallel::classes( + scope, [&dfa_classes, &nested_dfa_classes](DexClass* clazz) { + for (const DexClass* exported_class : dfa_classes) { + auto dex_klass_prefix = exported_class->get_name()->str_copy(); + dex_klass_prefix.erase(dex_klass_prefix.length() - 1); + + if (boost::starts_with(show(clazz), dex_klass_prefix)) { + nested_dfa_classes.emplace(clazz); + } + } + }); + } + + dfa_classes.insert(nested_dfa_classes.begin(), nested_dfa_classes.end()); + + std::vector models; + for (const auto* dex_klass : dfa_classes) { + // Mark all public and protected methods in the class as exported. + for (const auto* dex_callee : dex_klass->get_all_methods()) { + if (dex_callee == nullptr) { + continue; + } + + if (dex_callee->get_access() & DexAccessFlags::ACC_PRIVATE) { + continue; + } + + const auto* callee = methods.get(dex_callee); + if (callee == nullptr) { + continue; + } + + Model model(callee, context_); + model.add_call_effect_source( + AccessPath(Root(Root::Kind::CallEffectExploitability)), + generator::source( + context_, + /* kind */ "DfaComponent"), + *context_.heuristics); + models.push_back(model); + } + } + return models; +} + +} // namespace marianatrench diff --git a/source/model-generator/DFASourceGenerator.h b/source/model-generator/DFASourceGenerator.h new file mode 100644 index 00000000..59f4cff0 --- /dev/null +++ b/source/model-generator/DFASourceGenerator.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace marianatrench { + +class DFASourceGenerator : public ModelGenerator { + public: + explicit DFASourceGenerator(Context& context); + + std::vector emit_method_models(const Methods&) override; + + private: + std::string resources_directory_; +}; + +} // namespace marianatrench