diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java index 6e0010789..e31e63c78 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java @@ -2,14 +2,17 @@ package jadx.core.dex.instructions.args; import jadx.core.dex.info.FieldInfo; +import org.jetbrains.annotations.Nullable; + // TODO: don't extend RegisterArg (now used as a result of instruction) public final class FieldArg extends RegisterArg { private final FieldInfo field; // instArg equal 'null' for static fields + @Nullable private final InsnArg instArg; - public FieldArg(FieldInfo field, InsnArg reg) { + public FieldArg(FieldInfo field, @Nullable InsnArg reg) { super(-1); this.instArg = reg; this.field = field; diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java index 993c52010..b78b4f5ca 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java @@ -2,11 +2,13 @@ package jadx.core.dex.instructions.args; import jadx.core.dex.nodes.InsnNode; +import org.jetbrains.annotations.NotNull; + public final class InsnWrapArg extends InsnArg { private final InsnNode wrappedInsn; - public InsnWrapArg(InsnNode insn) { + public InsnWrapArg(@NotNull InsnNode insn) { RegisterArg result = insn.getResult(); this.type = result != null ? result.getType() : ArgType.VOID; this.wrappedInsn = insn; @@ -27,6 +29,34 @@ public final class InsnWrapArg extends InsnArg { return true; } + @Override + public int hashCode() { + return wrappedInsn.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof InsnWrapArg)) { + return false; + } + InsnWrapArg that = (InsnWrapArg) o; + InsnNode thisInsn = wrappedInsn; + InsnNode thatInsn = that.wrappedInsn; + if (!thisInsn.isSame(thatInsn)) { + return false; + } + int count = thisInsn.getArgsCount(); + for (int i = 0; i < count; i++) { + if (!thisInsn.getArg(i).equals(thatInsn.getArg(i))) { + return false; + } + } + return true; + } + @Override public String toString() { return "(wrap: " + type + "\n " + wrappedInsn + ")"; diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/NamedArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/NamedArg.java index dbca35ead..cef1b4d05 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/NamedArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/NamedArg.java @@ -1,14 +1,18 @@ package jadx.core.dex.instructions.args; +import org.jetbrains.annotations.NotNull; + public final class NamedArg extends InsnArg implements Named { + @NotNull private String name; - public NamedArg(String name, ArgType type) { + public NamedArg(@NotNull String name, @NotNull ArgType type) { this.name = name; this.type = type; } + @NotNull public String getName() { return name; } @@ -18,10 +22,27 @@ public final class NamedArg extends InsnArg implements Named { return true; } - public void setName(String name) { + public void setName(@NotNull String name) { this.name = name; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof NamedArg)) { + return false; + } + return name.equals(((NamedArg) o).name); + + } + + @Override + public int hashCode() { + return name.hashCode(); + } + @Override public String toString() { return "(" + name + " " + type + ")"; diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/TypeImmutableArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/TypeImmutableArg.java index 43f21c1a1..3722b1d8f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/TypeImmutableArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/TypeImmutableArg.java @@ -55,8 +55,7 @@ public class TypeImmutableArg extends RegisterArg { if (!super.equals(obj)) { return false; } - TypeImmutableArg that = (TypeImmutableArg) obj; - return isThis == that.isThis; + return isThis == ((TypeImmutableArg) obj).isThis; } @Override diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java index d3789ff23..feeb7aded 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java @@ -137,7 +137,7 @@ public class SimplifyVisitor extends AbstractVisitor { private static InsnNode convertInvoke(MethodNode mth, InsnNode insn) { MethodInfo callMth = ((InvokeNode) insn).getCallMth(); - // If this is a 'new StringBuilder(xxx).append(yyy).append(zzz).toString(), + // If this is a 'new StringBuilder(xxx).append(yyy).append(zzz).toString(), // convert it to STRING_CONCAT pseudo instruction. if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER) && callMth.getShortId().equals(Consts.MTH_TOSTRING_SIGNATURE) @@ -150,11 +150,11 @@ public class SimplifyVisitor extends AbstractVisitor { if (chain.size()>1 && chain.get(0).getType()==InsnType.CONSTRUCTOR) { constrIndex = 0; } else if (chain.size()>2 && chain.get(1).getType()==InsnType.CONSTRUCTOR) { - //RAF Case where the first string element is String arg to the + //RAF Case where the first string element is String arg to the // new StringBuilder("xxx") constructor constrIndex = 1; } else if (chain.size()>3 && chain.get(2).getType()==InsnType.CONSTRUCTOR) { - //RAF Case where the first string element is String.valueOf() arg + //RAF Case where the first string element is String.valueOf() arg // to the new StringBuilder(String.valueOf(zzz)) constructor constrIndex = 2; } @@ -167,7 +167,7 @@ public class SimplifyVisitor extends AbstractVisitor { InsnNode argInsn; if (constrIndex > 0) { // There was an arg to the StringBuilder constr InsnWrapArg iwa; - if (constrIndex==2 + if (constrIndex==2 && (argInsn = chain.get(1)).getType()==InsnType.INVOKE && ((InvokeNode)argInsn).getCallMth().getName().compareTo("valueOf")==0) { // The argument of new StringBuilder() is a String.valueOf(chainElement0) @@ -181,7 +181,7 @@ public class SimplifyVisitor extends AbstractVisitor { concatInsn.addArg(iwa); } - for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat + for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat concatInsn.addArg(chain.get(argInd).getArg(1)); } concatInsn.setResult(insn.getResult()); @@ -252,6 +252,10 @@ public class SimplifyVisitor extends AbstractVisitor { InsnArg reg = null; if (getType == InsnType.IGET) { reg = get.getArg(0); + InsnArg putReg = insn.getArg(1); + if (!reg.equals(putReg)) { + return null; + } } FieldArg fArg = new FieldArg(field, reg); if (reg != null) { @@ -268,7 +272,7 @@ public class SimplifyVisitor extends AbstractVisitor { } return new ArithNode(ArithOp.ADD, fArg, InsnArg.wrapArg(concat)); } - } catch (Throwable e) { + } catch (Exception e) { LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e); } return null; @@ -289,4 +293,4 @@ public class SimplifyVisitor extends AbstractVisitor { Collections.reverse(chain); return chain; } -} \ No newline at end of file +} diff --git a/jadx-core/src/test/java/jadx/tests/integration/arith/TestFieldIncrement3.java b/jadx-core/src/test/java/jadx/tests/integration/arith/TestFieldIncrement3.java new file mode 100644 index 000000000..1a59961e0 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/arith/TestFieldIncrement3.java @@ -0,0 +1,75 @@ +package jadx.tests.integration.arith; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import java.util.Random; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +public class TestFieldIncrement3 extends IntegrationTest { + + public static class TestCls { + static int tileX; + static int tileY; + static Vector2 targetPos = new Vector2(); + static Vector2 directVect = new Vector2(); + static Vector2 newPos = new Vector2(); + + private static void test() { + Random rd = new Random(); + int direction = rd.nextInt(7); + switch (direction) { + case 0: + targetPos.x = (float) (((tileX + 1) * 55) + 55); + targetPos.y = (float) (((tileY + 1) * 35) + 35); + break; + case 2: + targetPos.x = (float) (((tileX + 1) * 55) + 55); + targetPos.y = (float) (((tileY - 1) * 35) + 35); + break; + case 4: + targetPos.x = (float) (((tileX - 1) * 55) + 55); + targetPos.y = (float) (((tileY - 1) * 35) + 35); + break; + case 6: + targetPos.x = (float) (((tileX - 1) * 55) + 55); + targetPos.y = (float) (((tileY + 1) * 35) + 35); + break; + default: + break; + } + directVect.x = targetPos.x - newPos.x; + directVect.y = targetPos.y - newPos.y; + + float hPos = (float) Math.sqrt((double) ((directVect.x * directVect.x) + (directVect.y * directVect.y))); + directVect.x /= hPos; + directVect.y /= hPos; + } + + static class Vector2 { + public float x; + public float y; + + public Vector2() { + this.x = 0.0f; + this.y = 0.0f; + } + + public boolean equals(Vector2 other) { + return (this.x == other.x && this.y == other.y); + } + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsString("directVect.x = targetPos.x - newPos.x;")); + } +}