Projects STRLCPY jadx Commits 87e0e5bf
🤬
  • fix: correct inline/merge with overriden bridge method (#1580)

  • Loading...
  • Skylot committed 2 years ago
    87e0e5bf
    1 parent e4c2d6cf
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/api/metadata/annotations/NodeDeclareRef.java
    skipped 32 lines
    33 33   }
    34 34   
    35 35   @Override
     36 + public boolean equals(Object o) {
     37 + if (this == o) {
     38 + return true;
     39 + }
     40 + if (!(o instanceof NodeDeclareRef)) {
     41 + return false;
     42 + }
     43 + return node.equals(((NodeDeclareRef) o).node);
     44 + }
     45 + 
     46 + @Override
     47 + public int hashCode() {
     48 + return node.hashCode();
     49 + }
     50 + 
     51 + @Override
    36 52   public String toString() {
    37 53   return "NodeDeclareRef{" + node + '}';
    38 54   }
    skipped 2 lines
  • ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
    skipped 25 lines
    26 26  import jadx.core.dex.attributes.nodes.JadxError;
    27 27  import jadx.core.dex.attributes.nodes.JumpInfo;
    28 28  import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
     29 +import jadx.core.dex.attributes.nodes.MethodReplaceAttr;
    29 30  import jadx.core.dex.info.AccessInfo;
    30 31  import jadx.core.dex.instructions.ConstStringNode;
    31 32  import jadx.core.dex.instructions.IfNode;
    skipped 112 lines
    144 145   } else {
    145 146   classGen.useType(code, mth.getReturnType());
    146 147   code.add(' ');
    147  - code.attachDefinition(mth);
    148  - code.add(mth.getAlias());
     148 + MethodNode defMth = getMethodForDefinition();
     149 + code.attachDefinition(defMth);
     150 + code.add(defMth.getAlias());
    149 151   }
    150 152   code.add('(');
    151 153   
    skipped 24 lines
    176 178   }
    177 179   }
    178 180   return true;
     181 + }
     182 + 
     183 + private MethodNode getMethodForDefinition() {
     184 + MethodReplaceAttr replaceAttr = mth.get(AType.METHOD_REPLACE);
     185 + if (replaceAttr != null) {
     186 + return replaceAttr.getReplaceMth();
     187 + }
     188 + return mth;
    179 189   }
    180 190   
    181 191   private void addOverrideAnnotation(ICodeWriter code, MethodNode mth) {
    skipped 383 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
    skipped 9 lines
    10 10  import jadx.api.plugins.input.data.AccessFlags;
    11 11  import jadx.core.Consts;
    12 12  import jadx.core.dex.attributes.AFlag;
     13 +import jadx.core.dex.attributes.AType;
    13 14  import jadx.core.dex.attributes.nodes.FieldReplaceAttr;
    14 15  import jadx.core.dex.attributes.nodes.MethodReplaceAttr;
    15 16  import jadx.core.dex.attributes.nodes.SkipMethodArgsAttr;
    skipped 265 lines
    281 282   if (!Objects.equals(wrappedMth.getAlias(), alias)) {
    282 283   wrappedMth.getMethodInfo().setAlias(alias);
    283 284   }
     285 + wrappedMth.addAttr(new MethodReplaceAttr(mth));
     286 + wrappedMth.copyAttributeFrom(mth, AType.METHOD_OVERRIDE);
     287 + wrappedMth.addDebugComment("Method merged with bridge method");
    284 288   return true;
    285 289   }
    286 290   
    skipped 133 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxClassNodeAssertions.java
    skipped 7 lines
    8 8  import jadx.api.ICodeInfo;
    9 9  import jadx.api.metadata.ICodeAnnotation;
    10 10  import jadx.core.dex.nodes.ClassNode;
    11  -import jadx.core.dex.nodes.ICodeNode;
    12 11  import jadx.tests.api.IntegrationTest;
    13 12   
    14 13  import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
    skipped 43 lines
    58 57   return this;
    59 58   }
    60 59   
    61  - public void checkCodeAnnotationFor(String refStr, ICodeNode node) {
     60 + public JadxClassNodeAssertions checkCodeAnnotationFor(String refStr, ICodeAnnotation node) {
    62 61   checkCodeAnnotationFor(refStr, 0, node);
     62 + return this;
    63 63   }
    64 64   
    65  - public void checkCodeAnnotationFor(String refStr, int refOffset, ICodeNode node) {
     65 + public JadxClassNodeAssertions checkCodeAnnotationFor(String refStr, int refOffset, ICodeAnnotation node) {
    66 66   ICodeInfo code = actual.getCode();
    67 67   int codePos = code.getCodeStr().indexOf(refStr);
    68 68   assertThat(codePos).describedAs("String '%s' not found", refStr).isNotEqualTo(-1);
    skipped 1 lines
    70 70   for (Map.Entry<Integer, ICodeAnnotation> entry : code.getCodeMetadata().getAsMap().entrySet()) {
    71 71   if (entry.getKey() == refPos) {
    72 72   Assertions.assertThat(entry.getValue()).isEqualTo(node);
    73  - return;
     73 + return this;
    74 74   }
    75 75   }
    76 76   fail("Annotation for reference string: '%s' at position %d not found", refStr, refPos);
     77 + return this;
    77 78   }
    78 79  }
    79 80   
  • ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/integration/generics/TestGenericsMthOverride.java
    skipped 55 lines
    56 56   assertThat(code, containsOne("public Y method(Exception x) {"));
    57 57   assertThat(code, containsOne("public Object method(Object x) {"));
    58 58   
    59  - assertThat(code, countString(3, "@Override"));
    60  - // TODO: @Override missing for class C
    61  - // assertThat(code, countString(4, "@Override"));
     59 + assertThat(code, countString(4, "@Override"));
    62 60   }
    63 61  }
    64 62   
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/integration/inline/TestOverrideBridgeMerge.java
     1 +package jadx.tests.integration.inline;
     2 + 
     3 +import java.util.function.Function;
     4 + 
     5 +import org.junit.jupiter.api.Test;
     6 + 
     7 +import jadx.api.metadata.ICodeAnnotation;
     8 +import jadx.api.metadata.annotations.NodeDeclareRef;
     9 +import jadx.core.dex.nodes.ClassNode;
     10 +import jadx.tests.api.SmaliTest;
     11 + 
     12 +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
     13 + 
     14 +public class TestOverrideBridgeMerge extends SmaliTest {
     15 + 
     16 + public static class TestCls implements Function<String, Integer> {
     17 + @Override
     18 + public /* bridge */ /* synthetic */ Integer apply(String str) {
     19 + return test(str);
     20 + }
     21 + 
     22 + public Integer test(String str) {
     23 + return str.length();
     24 + }
     25 + }
     26 + 
     27 + @Test
     28 + public void test() {
     29 + assertThat(getClassNode(TestCls.class))
     30 + .code()
     31 + .containsOne("Integer test(String str) {"); // not inlined
     32 + }
     33 + 
     34 + @Test
     35 + public void testSmali() {
     36 + ClassNode cls = getClassNodeFromSmali();
     37 + ICodeAnnotation mthDef = new NodeDeclareRef(getMethod(cls, "apply"));
     38 + assertThat(cls)
     39 + .checkCodeAnnotationFor("apply(String str) {", mthDef)
     40 + .code()
     41 + .containsOne("@Override")
     42 + .containsOne("public Integer apply(String str) {")
     43 + .doesNotContain("test(String str)");
     44 + }
     45 +}
     46 + 
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/smali/inline/TestOverrideBridgeMerge.smali
     1 +.class public Linline/TestOverrideBridgeMerge;
     2 +.super Ljava/lang/Object;
     3 + 
     4 +.implements Ljava/util/function/Function;
     5 + 
     6 +.annotation system Ldalvik/annotation/Signature;
     7 + value = {
     8 + "Ljava/lang/Object;",
     9 + "Ljava/util/function/Function",
     10 + "<",
     11 + "Ljava/lang/String;",
     12 + "Ljava/lang/Integer;",
     13 + ">;"
     14 + }
     15 +.end annotation
     16 + 
     17 +.method public constructor <init>()V
     18 + .registers 1
     19 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V
     20 + return-void
     21 +.end method
     22 + 
     23 +.method public bridge synthetic apply(Ljava/lang/Object;)Ljava/lang/Object;
     24 + .registers 3
     25 + check-cast p1, Ljava/lang/String;
     26 + invoke-virtual {p0, p1}, Linline/TestOverrideBridgeMerge;->test(Ljava/lang/String;)Ljava/lang/Integer;
     27 + move-result-object v0
     28 + return-object v0
     29 +.end method
     30 + 
     31 +.method public test(Ljava/lang/String;)Ljava/lang/Integer;
     32 + .registers 3
     33 + .param p1, "str" # Ljava/lang/String;
     34 + invoke-virtual {p1}, Ljava/lang/String;->length()I
     35 + move-result v0
     36 + invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
     37 + move-result-object v0
     38 + return-object v0
     39 +.end method
     40 + 
Please wait...
Page is in error, reload to recover