From 6620e650efde8d98c43df6b1e5b6c4bf367a9a41 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 19 Jun 2023 15:05:06 +0100 Subject: [PATCH] fix: check args of inlined insns on reorder (#1919) --- .../core/dex/visitors/shrink/ArgsInfo.java | 37 +++++++++++------ .../code/TestArrayAccessReorder.java | 40 +++++++++++++++++++ 2 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/code/TestArrayAccessReorder.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 95c97ecf..74a1cc1f 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 @@ -13,6 +13,7 @@ import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.mods.TernaryInsn; import jadx.core.dex.nodes.InsnNode; import jadx.core.utils.EmptyBitSet; +import jadx.core.utils.Utils; import jadx.core.utils.exceptions.JadxRuntimeException; final class ArgsInfo { @@ -62,6 +63,27 @@ final class ArgsInfo { return args; } + public BitSet getArgsSet() { + if (args.isEmpty() && Utils.isEmpty(wrappedInsns)) { + return EmptyBitSet.EMPTY; + } + BitSet set = new BitSet(); + fillArgsSet(set); + return set; + } + + private void fillArgsSet(BitSet set) { + for (RegisterArg arg : args) { + set.set(arg.getRegNum()); + } + List wrapList = wrappedInsns; + if (wrapList != null) { + for (ArgsInfo wrappedInsn : wrapList) { + wrappedInsn.fillArgsSet(set); + } + } + } + public WrapInfo checkInline(int assignPos, RegisterArg arg) { if (assignPos >= inlineBorder || !canMove(assignPos, inlineBorder)) { return null; @@ -80,18 +102,9 @@ final class ArgsInfo { if (start > to) { throw new JadxRuntimeException("Invalid inline insn positions: " + start + " - " + to); } - BitSet movedSet; - List movedArgs = startInfo.getArgs(); - if (movedArgs.isEmpty()) { - if (startInfo.insn.isConstInsn()) { - return true; - } - movedSet = EmptyBitSet.EMPTY; - } else { - movedSet = new BitSet(); - for (RegisterArg arg : movedArgs) { - movedSet.set(arg.getRegNum()); - } + BitSet movedSet = startInfo.getArgsSet(); + if (movedSet == EmptyBitSet.EMPTY && startInfo.insn.isConstInsn()) { + return true; } boolean canReorder = startInfo.canReorder(); for (int i = start; i < to; i++) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/code/TestArrayAccessReorder.java b/jadx-core/src/test/java/jadx/tests/integration/code/TestArrayAccessReorder.java new file mode 100644 index 00000000..67c16558 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/code/TestArrayAccessReorder.java @@ -0,0 +1,40 @@ +package jadx.tests.integration.code; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestArrayAccessReorder extends IntegrationTest { + + public static class TestCls { + public int[] test(int[] arr) { + int len = arr.length; + int[] result = new int[len]; + int i = 0; + int k = len; + while (k != 0) { + int v = arr[i]; + k--; + int t = -v; + i++; + result[k] = t * 5; + } + return result; + } + + public void check() { + assertThat(test(new int[] { 1, 2, 3 })).isEqualTo(new int[] { -15, -10, -5 }); + } + } + + @Test + public void test() { + noDebugInfo(); + getArgs().setRawCFGOutput(true); + assertThat(getClassNode(TestCls.class)) + .code() + .containsOne("i++"); + } +}