From 1b98be0b0a723b131c24735c3b6031c101ebc7b9 Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 17 Feb 2015 14:48:42 +0300 Subject: [PATCH] core: fix array type for new-array instruction (fix #50) --- .../main/java/jadx/core/codegen/InsnGen.java | 3 +- .../dex/instructions/FilledNewArrayNode.java | 4 +- .../core/dex/instructions/InsnDecoder.java | 5 ++- .../core/dex/instructions/NewArrayNode.java | 41 +++++++++++++++++++ .../dex/visitors/ConstInlinerVisitor.java | 4 +- .../jadx/core/dex/visitors/ModVisitor.java | 4 +- .../jadx/core/dex/visitors/ReSugarCode.java | 13 +++--- .../tests/integration/arrays/TestArrays3.java | 32 +++++++++++++++ 8 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 jadx-core/src/main/java/jadx/core/dex/instructions/NewArrayNode.java create mode 100644 jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrays3.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 b677bdcb9..4f23e1e22 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -20,6 +20,7 @@ import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InvokeNode; import jadx.core.dex.instructions.InvokeType; +import jadx.core.dex.instructions.NewArrayNode; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.FieldArg; @@ -341,7 +342,7 @@ public class InsnGen { break; case NEW_ARRAY: { - ArgType arrayType = insn.getResult().getType(); + ArgType arrayType = ((NewArrayNode) insn).getArrayType(); code.add("new "); useType(code, arrayType.getArrayRootElement()); code.add('['); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/FilledNewArrayNode.java b/jadx-core/src/main/java/jadx/core/dex/instructions/FilledNewArrayNode.java index 58d6cd063..c6cb7fcd6 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/FilledNewArrayNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/FilledNewArrayNode.java @@ -3,11 +3,13 @@ package jadx.core.dex.instructions; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.nodes.InsnNode; +import org.jetbrains.annotations.NotNull; + public class FilledNewArrayNode extends InsnNode { private final ArgType elemType; - public FilledNewArrayNode(ArgType elemType, int size) { + public FilledNewArrayNode(@NotNull ArgType elemType, int size) { super(InsnType.FILLED_NEW_ARRAY, size); this.elemType = elemType; } 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 68ca3da98..91c09cd78 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 @@ -535,8 +535,9 @@ public class InsnDecoder { InsnArg.reg(insn, 0, dex.getType(insn.getIndex()))); case Opcodes.NEW_ARRAY: - return insn(InsnType.NEW_ARRAY, - InsnArg.reg(insn, 0, dex.getType(insn.getIndex())), + ArgType arrType = dex.getType(insn.getIndex()); + return new NewArrayNode(arrType, + InsnArg.reg(insn, 0, arrType), InsnArg.reg(insn, 1, ArgType.INT)); case Opcodes.FILL_ARRAY_DATA: diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/NewArrayNode.java b/jadx-core/src/main/java/jadx/core/dex/instructions/NewArrayNode.java new file mode 100644 index 000000000..24d34cb6e --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/NewArrayNode.java @@ -0,0 +1,41 @@ +package jadx.core.dex.instructions; + +import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.InsnArg; +import jadx.core.dex.instructions.args.RegisterArg; +import jadx.core.dex.nodes.InsnNode; + +import org.jetbrains.annotations.NotNull; + +public class NewArrayNode extends InsnNode { + + private final ArgType arrType; + + public NewArrayNode(@NotNull ArgType arrType, RegisterArg res, InsnArg size) { + super(InsnType.NEW_ARRAY, 1); + this.arrType = arrType; + setResult(res); + addArg(size); + } + + public ArgType getArrayType() { + return arrType; + } + + @Override + public boolean isSame(InsnNode obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof NewArrayNode) || !super.isSame(obj)) { + return false; + } + NewArrayNode other = (NewArrayNode) obj; + return arrType == other.arrType; + } + + @Override + public String toString() { + return super.toString() + " type: " + arrType; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java index 871d4219a..1e2c046a8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java @@ -222,7 +222,9 @@ public class ConstInlinerVisitor extends AbstractVisitor { break; case NEW_ARRAY: - litArg.merge(ArgType.INT); + if (litArg == insn.getArg(0)) { + litArg.merge(ArgType.INT); + } break; default: diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index fbd5a961e..aac7a0f28 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -12,6 +12,7 @@ import jadx.core.dex.instructions.FilledNewArrayNode; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InvokeNode; +import jadx.core.dex.instructions.NewArrayNode; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; @@ -108,7 +109,8 @@ public class ModVisitor extends AbstractVisitor { InsnNode ni = block.getInstructions().get(next); if (ni.getType() == InsnType.FILL_ARRAY) { ni.getResult().merge(insn.getResult()); - ((FillArrayNode) ni).mergeElementType(insn.getResult().getType().getArrayElement()); + ArgType arrType = ((NewArrayNode) insn).getArrayType(); + ((FillArrayNode) ni).mergeElementType(arrType.getArrayElement()); remover.add(insn); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java index 44fd2f1bc..a9f0876ce 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java @@ -9,6 +9,7 @@ import jadx.core.dex.instructions.FilledNewArrayNode; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InvokeNode; +import jadx.core.dex.instructions.NewArrayNode; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; @@ -70,19 +71,21 @@ public class ReSugarCode extends AbstractVisitor { */ private static InsnNode processNewArray(MethodNode mth, List instructions, int i, InstructionRemover remover) { - InsnNode insn = instructions.get(i); - InsnArg arg = insn.getArg(0); + NewArrayNode newArrayInsn = (NewArrayNode) instructions.get(i); + InsnArg arg = newArrayInsn.getArg(0); if (!arg.isLiteral()) { return null; } int len = (int) ((LiteralArg) arg).getLiteral(); int size = instructions.size(); - if (len <= 0 || i + len >= size || instructions.get(i + len).getType() != InsnType.APUT) { + if (len <= 0 + || i + len >= size + || instructions.get(i + len).getType() != InsnType.APUT) { return null; } - ArgType arrType = insn.getResult().getType(); + ArgType arrType = newArrayInsn.getArrayType(); InsnNode filledArr = new FilledNewArrayNode(arrType.getArrayElement(), len); - filledArr.setResult(insn.getResult()); + filledArr.setResult(newArrayInsn.getResult()); for (int j = 0; j < len; j++) { InsnNode put = instructions.get(i + 1 + j); if (put.getType() != InsnType.APUT) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrays3.java b/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrays3.java new file mode 100644 index 000000000..c4a601db8 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrays3.java @@ -0,0 +1,32 @@ +package jadx.tests.integration.arrays; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertThat; + +public class TestArrays3 extends IntegrationTest { + public static class TestCls { + + private Object test(byte[] bArr) { + return new Object[]{bArr}; + } + + public void check() { + assertThat(test(new byte[]{1, 2}), instanceOf(Object[].class)); + } + } + + @Test + public void test() { + noDebugInfo(); + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("return new Object[]{bArr};")); + } +}