Skip to content

Commit

Permalink
fix: correct inline/merge with overriden bridge method (#1580)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 20, 2022
1 parent e4c2d6c commit 87e0e5b
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ public AnnType getAnnType() {
return AnnType.DECLARATION;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NodeDeclareRef)) {
return false;
}
return node.equals(((NodeDeclareRef) o).node);
}

@Override
public int hashCode() {
return node.hashCode();
}

@Override
public String toString() {
return "NodeDeclareRef{" + node + '}';
Expand Down
14 changes: 12 additions & 2 deletions jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import jadx.core.dex.attributes.nodes.JadxError;
import jadx.core.dex.attributes.nodes.JumpInfo;
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
import jadx.core.dex.attributes.nodes.MethodReplaceAttr;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.instructions.ConstStringNode;
import jadx.core.dex.instructions.IfNode;
Expand Down Expand Up @@ -144,8 +145,9 @@ public boolean addDefinition(ICodeWriter code) {
} else {
classGen.useType(code, mth.getReturnType());
code.add(' ');
code.attachDefinition(mth);
code.add(mth.getAlias());
MethodNode defMth = getMethodForDefinition();
code.attachDefinition(defMth);
code.add(defMth.getAlias());
}
code.add('(');

Expand Down Expand Up @@ -178,6 +180,14 @@ public boolean addDefinition(ICodeWriter code) {
return true;
}

private MethodNode getMethodForDefinition() {
MethodReplaceAttr replaceAttr = mth.get(AType.METHOD_REPLACE);
if (replaceAttr != null) {
return replaceAttr.getReplaceMth();
}
return mth;
}

private void addOverrideAnnotation(ICodeWriter code, MethodNode mth) {
MethodOverrideAttr overrideAttr = mth.get(AType.METHOD_OVERRIDE);
if (overrideAttr == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jadx.api.plugins.input.data.AccessFlags;
import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.FieldReplaceAttr;
import jadx.core.dex.attributes.nodes.MethodReplaceAttr;
import jadx.core.dex.attributes.nodes.SkipMethodArgsAttr;
Expand Down Expand Up @@ -281,6 +282,9 @@ private static boolean checkSyntheticWrapper(MethodNode mth, InsnNode insn) {
if (!Objects.equals(wrappedMth.getAlias(), alias)) {
wrappedMth.getMethodInfo().setAlias(alias);
}
wrappedMth.addAttr(new MethodReplaceAttr(mth));
wrappedMth.copyAttributeFrom(mth, AType.METHOD_OVERRIDE);
wrappedMth.addDebugComment("Method merged with bridge method");
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import jadx.api.ICodeInfo;
import jadx.api.metadata.ICodeAnnotation;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.ICodeNode;
import jadx.tests.api.IntegrationTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
Expand Down Expand Up @@ -58,21 +57,23 @@ public JadxClassNodeAssertions runDecompiledAutoCheck(IntegrationTest testInstan
return this;
}

public void checkCodeAnnotationFor(String refStr, ICodeNode node) {
public JadxClassNodeAssertions checkCodeAnnotationFor(String refStr, ICodeAnnotation node) {
checkCodeAnnotationFor(refStr, 0, node);
return this;
}

public void checkCodeAnnotationFor(String refStr, int refOffset, ICodeNode node) {
public JadxClassNodeAssertions checkCodeAnnotationFor(String refStr, int refOffset, ICodeAnnotation node) {
ICodeInfo code = actual.getCode();
int codePos = code.getCodeStr().indexOf(refStr);
assertThat(codePos).describedAs("String '%s' not found", refStr).isNotEqualTo(-1);
int refPos = codePos + refOffset;
for (Map.Entry<Integer, ICodeAnnotation> entry : code.getCodeMetadata().getAsMap().entrySet()) {
if (entry.getKey() == refPos) {
Assertions.assertThat(entry.getValue()).isEqualTo(node);
return;
return this;
}
}
fail("Annotation for reference string: '%s' at position %d not found", refStr, refPos);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ public void test() {
assertThat(code, containsOne("public Y method(Exception x) {"));
assertThat(code, containsOne("public Object method(Object x) {"));

assertThat(code, countString(3, "@Override"));
// TODO: @Override missing for class C
// assertThat(code, countString(4, "@Override"));
assertThat(code, countString(4, "@Override"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package jadx.tests.integration.inline;

import java.util.function.Function;

import org.junit.jupiter.api.Test;

import jadx.api.metadata.ICodeAnnotation;
import jadx.api.metadata.annotations.NodeDeclareRef;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;

public class TestOverrideBridgeMerge extends SmaliTest {

public static class TestCls implements Function<String, Integer> {
@Override
public /* bridge */ /* synthetic */ Integer apply(String str) {
return test(str);
}

public Integer test(String str) {
return str.length();
}
}

@Test
public void test() {
assertThat(getClassNode(TestCls.class))
.code()
.containsOne("Integer test(String str) {"); // not inlined
}

@Test
public void testSmali() {
ClassNode cls = getClassNodeFromSmali();
ICodeAnnotation mthDef = new NodeDeclareRef(getMethod(cls, "apply"));
assertThat(cls)
.checkCodeAnnotationFor("apply(String str) {", mthDef)
.code()
.containsOne("@Override")
.containsOne("public Integer apply(String str) {")
.doesNotContain("test(String str)");
}
}
39 changes: 39 additions & 0 deletions jadx-core/src/test/smali/inline/TestOverrideBridgeMerge.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.class public Linline/TestOverrideBridgeMerge;
.super Ljava/lang/Object;

.implements Ljava/util/function/Function;

.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/lang/Object;",
"Ljava/util/function/Function",
"<",
"Ljava/lang/String;",
"Ljava/lang/Integer;",
">;"
}
.end annotation

.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method

.method public bridge synthetic apply(Ljava/lang/Object;)Ljava/lang/Object;
.registers 3
check-cast p1, Ljava/lang/String;
invoke-virtual {p0, p1}, Linline/TestOverrideBridgeMerge;->test(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object v0
return-object v0
.end method

.method public test(Ljava/lang/String;)Ljava/lang/Integer;
.registers 3
.param p1, "str" # Ljava/lang/String;
invoke-virtual {p1}, Ljava/lang/String;->length()I
move-result v0
invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
move-result-object v0
return-object v0
.end method

0 comments on commit 87e0e5b

Please sign in to comment.