Skip to content

Commit

Permalink
Add integrity check
Browse files Browse the repository at this point in the history
Summary: Add an optional check that all types with a given prefix are defined.

Reviewed By: danjin250

Differential Revision: D66666167

fbshipit-source-id: e99709feee2a6b34ed63bf50a4236afa987a2b94
  • Loading branch information
agampe authored and facebook-github-bot committed Dec 11, 2024
1 parent 3801599 commit bdf76d7
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
67 changes: 67 additions & 0 deletions opt/instrument/Instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,64 @@ void set_no_opt_flag_on_analysis_methods(
}
}

size_t check_integrity(DexStoresVector& stores, const std::string& prefix) {
auto scope = build_class_scope(stores);
InsertOnlyConcurrentSet<DexType*> checked_types;
auto check_type = [&prefix, &checked_types](DexType* type) {
if (type->get_name()->str().find(prefix) != 0) {
return true;
}
checked_types.insert(type);
return type_class(type) != nullptr;
};
walk::parallel::classes(scope, [&](DexClass* cls) {
check_type(cls->get_type()); // Just for counting purposes.
check_type(cls->get_super_class());
if (cls->get_interfaces() != nullptr) {
for (auto* intf : *cls->get_interfaces()) {
check_type(intf);
}
}
for (auto* field : cls->get_all_fields()) {
always_assert_log(check_type(field->get_type()), "%s", SHOW(field));
}
});
walk::parallel::methods(scope, [&](DexMethod* m) {
auto code = m->get_code();
if (code == nullptr) {
return;
}
cfg::ScopedCFG cfg{code};
for (auto& mie : cfg::InstructionIterable(*cfg)) {
auto insn = mie.insn;
always_assert_log(!insn->has_type() || check_type(insn->get_type()), "%s",
SHOW(insn));

always_assert_log(!insn->has_field() ||
check_type(insn->get_field()->get_type()),
"%s", SHOW(insn));
always_assert_log(!insn->has_field() ||
check_type(insn->get_field()->get_class()),
"%s", SHOW(insn));

always_assert_log(!insn->has_method() ||
check_type(insn->get_method()->get_class()),
"%s", SHOW(insn));
always_assert_log(
!insn->has_method() ||
check_type(insn->get_method()->get_proto()->get_rtype()),
"%s", SHOW(insn));
always_assert_log(
!insn->has_method() ||
std::all_of(insn->get_method()->get_proto()->get_args()->begin(),
insn->get_method()->get_proto()->get_args()->end(),
check_type),
"%s", SHOW(insn));
}
});
return checked_types.size();
}

} // namespace

void InstrumentPass::eval_pass(DexStoresVector& stores,
Expand All @@ -685,6 +743,11 @@ void InstrumentPass::eval_pass(DexStoresVector& stores,
return;
}

if (m_options.analysis_package_prefix) {
m_integrity_types =
check_integrity(stores, *m_options.analysis_package_prefix);
}

// Note: Could do the inverse and protect necessary members here.

set_no_opt_flag_on_analysis_methods(true, m_options.analysis_class_name,
Expand Down Expand Up @@ -1128,6 +1191,10 @@ void InstrumentPass::run_pass(DexStoresVector& stores,
// future.
set_no_opt_flag_on_analysis_methods(true, m_options.analysis_class_name,
m_options.analysis_method_names);

if (m_integrity_types) {
pm.set_metric("integrity_checked_types", *m_integrity_types);
}
}

static InstrumentPass s_pass;
1 change: 1 addition & 0 deletions opt/instrument/Instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class InstrumentPass : public Pass {
Options m_options;
std::unique_ptr<interdex::InterDexPassPlugin> m_plugin;
std::optional<ReserveRefsInfoHandle> m_reserved_refs_handle;
std::optional<size_t> m_integrity_types;
};

} // namespace instrument

0 comments on commit bdf76d7

Please sign in to comment.