From 7576f9cd5e0634fa2063ac9e89ca56ca7e8ecbc3 Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 11 Jan 2022 15:20:53 +0000 Subject: [PATCH] fix: wrap negative literals before cast (#1327) --- .../main/java/jadx/core/codegen/InsnGen.java | 11 +++++- .../core/dex/instructions/InsnDecoder.java | 12 +++++- .../invoke/TestOverloadedInvoke.java | 39 +++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/invoke/TestOverloadedInvoke.java diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 0ce18c02d..c2492030c 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -112,7 +112,7 @@ public class InsnGen { } code.add(mgen.getNameGen().useArg(reg)); } else if (arg.isLiteral()) { - code.add(lit((LiteralArg) arg)); + addLiteralArg(code, (LiteralArg) arg, flags); } else if (arg.isInsnWrap()) { addWrappedArg(code, (InsnWrapArg) arg, flags); } else if (arg.isNamed()) { @@ -122,6 +122,15 @@ public class InsnGen { } } + private void addLiteralArg(ICodeWriter code, LiteralArg litArg, Set flags) { + String literalStr = lit(litArg); + if (!flags.contains(Flags.BODY_ONLY_NOWRAP) && literalStr.startsWith("-")) { + code.add('(').add(literalStr).add(')'); + } else { + code.add(literalStr); + } + } + private void addWrappedArg(ICodeWriter code, InsnWrapArg arg, Set flags) throws CodegenException { InsnNode wrapInsn = arg.getWrapInsn(); if (wrapInsn.contains(AFlag.FORCE_ASSIGN_INLINE)) { diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java index af978a78d..ef52278ba 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java @@ -508,7 +508,17 @@ public class InsnDecoder { private InsnNode makeNewArray(InsnData insn) { ArgType indexType = ArgType.parse(insn.getIndexAsType()); int dim = (int) insn.getLiteral(); - ArgType arrType = dim == 0 ? indexType : ArgType.array(indexType, dim); + ArgType arrType; + if (dim == 0) { + arrType = indexType; + } else { + if (indexType.isArray()) { + // java bytecode can pass array as a base type + arrType = indexType; + } else { + arrType = ArgType.array(indexType, dim); + } + } int regsCount = insn.getRegsCount(); NewArrayNode newArr = new NewArrayNode(arrType, regsCount - 1); newArr.setResult(InsnArg.reg(insn, 0, arrType)); diff --git a/jadx-core/src/test/java/jadx/tests/integration/invoke/TestOverloadedInvoke.java b/jadx-core/src/test/java/jadx/tests/integration/invoke/TestOverloadedInvoke.java new file mode 100644 index 000000000..583b5e1e2 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/invoke/TestOverloadedInvoke.java @@ -0,0 +1,39 @@ +package jadx.tests.integration.invoke; + +import jadx.tests.api.IntegrationTest; +import jadx.tests.api.extensions.profiles.TestProfile; +import jadx.tests.api.extensions.profiles.TestWithProfiles; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestOverloadedInvoke extends IntegrationTest { + + public static class TestCls { + public static final int N = 10; + + public void test() { + int[][][] arr = new int[N][N][N]; + use(arr, -1); + use(arr[0], -2); + } + + public void use(Object[][] arr, Object obj) { + } + + public void use(int[][] arr, int i) { + } + } + + @TestWithProfiles({ TestProfile.DX_J8, TestProfile.D8_J11, TestProfile.JAVA8 }) + public void test() { + noDebugInfo(); + assertThat(getClassNode(TestCls.class)) + .code() + .containsOne("use(iArr[0], -2);") + .containsOne("use((Object[][]) iArr, (Object) (-1));"); + // TODO: don't add unnecessary casts + // .containsOne("use(iArr, -1);"); + // TODO: replace call `Array.newInstance` with new array creation: `new int[N][N][N]` + // .containsOne("new int[10][10][10];"); + } +}