From 38c3f8bf9aa54db377b230f7daef4c07e8c544d3 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sat, 10 Jun 2023 23:36:14 +0100 Subject: [PATCH] fix: additional insns reorder checks (#1904) --- .../core/dex/visitors/shrink/ArgsInfo.java | 26 ++++++++++++-- .../others/TestFieldAccessReorder.java | 35 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/others/TestFieldAccessReorder.java diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/ArgsInfo.java b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/ArgsInfo.java index a03b3b262..95c97ecf2 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/ArgsInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/ArgsInfo.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.List; +import org.jetbrains.annotations.Nullable; + import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnWrapArg; @@ -20,6 +22,7 @@ final class ArgsInfo { private final int pos; private int inlineBorder; private ArgsInfo inlinedInsn; + private @Nullable List wrappedInsns; public ArgsInfo(InsnNode insn, List argsList, int pos) { this.insn = insn; @@ -69,7 +72,6 @@ final class ArgsInfo { private boolean canMove(int from, int to) { ArgsInfo startInfo = argsList.get(from); - List movedArgs = startInfo.getArgs(); int start = from + 1; if (start == to) { // previous instruction or on edge of inline border @@ -79,6 +81,7 @@ final class ArgsInfo { throw new JadxRuntimeException("Invalid inline insn positions: " + start + " - " + to); } BitSet movedSet; + List movedArgs = startInfo.getArgs(); if (movedArgs.isEmpty()) { if (startInfo.insn.isConstInsn()) { return true; @@ -90,7 +93,7 @@ final class ArgsInfo { movedSet.set(arg.getRegNum()); } } - boolean canReorder = startInfo.insn.canReorder(); + boolean canReorder = startInfo.canReorder(); for (int i = start; i < to; i++) { ArgsInfo argsInfo = argsList.get(i); if (argsInfo.getInlinedInsn() == this) { @@ -110,6 +113,21 @@ final class ArgsInfo { return true; } + private boolean canReorder() { + if (!insn.canReorder()) { + return false; + } + List wrapList = wrappedInsns; + if (wrapList != null) { + for (ArgsInfo wrapInsn : wrapList) { + if (!wrapInsn.canReorder()) { + return false; + } + } + } + return true; + } + static boolean usedArgAssign(InsnNode insn, BitSet args) { if (args.isEmpty()) { return false; @@ -124,6 +142,10 @@ final class ArgsInfo { WrapInfo inline(int assignInsnPos, RegisterArg arg) { ArgsInfo argsInfo = argsList.get(assignInsnPos); argsInfo.inlinedInsn = this; + if (wrappedInsns == null) { + wrappedInsns = new ArrayList<>(args.size()); + } + wrappedInsns.add(argsInfo); return new WrapInfo(argsInfo.insn, arg); } diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldAccessReorder.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldAccessReorder.java new file mode 100644 index 000000000..1b8f41c99 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldAccessReorder.java @@ -0,0 +1,35 @@ +package jadx.tests.integration.others; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.IntegrationTest; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TestFieldAccessReorder extends IntegrationTest { + public static class TestCls { + private long field = 10; + + public final boolean test() { + long value = longCall(); + long diff = value - this.field; + this.field = value; + return diff > 250; + } + + public static long longCall() { + return 261L; + } + + public void check() { + assertTrue(test()); + } + } + + @Test + public void test() { + noDebugInfo(); + getClassNode(TestCls.class); + // auto check should pass + } +}