Skip to content

Commit

Permalink
Bypass delegates
Browse files Browse the repository at this point in the history
Summary: Bypass delegates such as P1697234372. If the field is a `$$delegate_` or has the same type as one of the interfaces, check that the invoked method has the same method signature and name as the caller itself and bypass the caller.

Reviewed By: thezhangwei

Differential Revision: D67328331

fbshipit-source-id: 66ae422c7c2a970c4d5f31ffac623c2ff139992a
  • Loading branch information
itang00 authored and facebook-github-bot committed Dec 17, 2024
1 parent fddf597 commit f7dd724
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
51 changes: 50 additions & 1 deletion opt/typedef-anno-checker/TypedefAnnoCheckerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1365,13 +1365,62 @@ bool TypedefAnnoChecker::is_value_of_opt(const DexMethod* m) {
return true;
}

bool TypedefAnnoChecker::is_delegate(const DexMethod* m) {
auto* cls = type_class(m->get_class());
DexTypeList* interfaces = cls->get_interfaces();

if (interfaces->empty()) {
return false;
}

auto& cfg = m->get_code()->cfg();
DexField* delegate = nullptr;

for (auto* block : cfg.blocks()) {
for (const auto& mie : InstructionIterable(block)) {
auto* insn = mie.insn;
if (insn->opcode() == OPCODE_IGET_OBJECT) {
DexField* field = insn->get_field()->as_def();
if (!field) {
continue;
}
// find methods that delegate with $$delegate_ P1697234372
if (boost::starts_with(field->get_simple_deobfuscated_name(),
"$$delegate_")) {
delegate = field;
} else {
// find methods that delegate without $$delegate_ P1698648093
// the field type must match one of the interfaces
for (auto interface : *interfaces) {
if (interface->get_name() == field->get_type()->get_name()) {
delegate = field;
}
}
}
} else if (opcode::is_an_invoke(insn->opcode()) && delegate) {
auto* callee = insn->get_method()->as_def();
if (!callee) {
continue;
}
if (m->get_simple_deobfuscated_name() ==
callee->get_simple_deobfuscated_name() &&
m->get_proto() == callee->get_proto()) {
TRACE(TAC, 2, "skipping delegate method %s", SHOW(m));
return true;
}
}
}
}
return false;
}

void TypedefAnnoChecker::run(DexMethod* m) {
IRCode* code = m->get_code();
if (!code) {
return;
}

if (is_value_of_opt(m)) {
if (is_value_of_opt(m) || is_delegate(m)) {
return;
}

Expand Down
1 change: 1 addition & 0 deletions opt/typedef-anno-checker/TypedefAnnoCheckerPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class TypedefAnnoChecker {
m_method_override_graph(method_override_graph) {}

bool is_value_of_opt(const DexMethod* m);
bool is_delegate(const DexMethod* m);

void run(DexMethod* m);

Expand Down

0 comments on commit f7dd724

Please sign in to comment.