Commit 1b98be0b authored by Skylot's avatar Skylot

core: fix array type for new-array instruction (fix #50)

parent e5b84d94
......@@ -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('[');
......
......@@ -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;
}
......
......@@ -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:
......
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;
}
}
......@@ -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:
......
......@@ -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);
}
}
......
......@@ -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<InsnNode> 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) {
......
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};"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment