Commit d6069820 authored by Skylot's avatar Skylot

core: fix type in fill-array instruction

parent c59b65e7
......@@ -30,6 +30,8 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.StringUtils;
import jadx.core.utils.exceptions.CodegenException;
......@@ -450,15 +452,19 @@ public class InsnGen {
}
private void fillArray(FillArrayNode insn, CodeWriter code) throws CodegenException {
ArgType elType = insn.getResult().getType().getArrayElement();
if (elType.getPrimitiveType() == null) {
elType = elType.selectFirst();
ArgType insnArrayType = insn.getResult().getType();
ArgType insnElementType = insnArrayType.getArrayElement();
ArgType elType = insn.getElementType();
if (!elType.equals(insnElementType) && !insnArrayType.equals(ArgType.OBJECT)) {
ErrorsCounter.methodError(mth,
"Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset()));
}
StringBuilder str = new StringBuilder();
Object data = insn.getData();
switch (elType.getPrimitiveType()) {
case BOOLEAN:
case BYTE:
byte[] array = (byte[]) insn.getData();
byte[] array = (byte[]) data;
for (byte b : array) {
str.append(TypeGen.literalToString(b, elType));
str.append(", ");
......@@ -466,7 +472,7 @@ public class InsnGen {
break;
case SHORT:
case CHAR:
short[] sarray = (short[]) insn.getData();
short[] sarray = (short[]) data;
for (short b : sarray) {
str.append(TypeGen.literalToString(b, elType));
str.append(", ");
......@@ -474,7 +480,7 @@ public class InsnGen {
break;
case INT:
case FLOAT:
int[] iarray = (int[]) insn.getData();
int[] iarray = (int[]) data;
for (int b : iarray) {
str.append(TypeGen.literalToString(b, elType));
str.append(", ");
......@@ -482,7 +488,7 @@ public class InsnGen {
break;
case LONG:
case DOUBLE:
long[] larray = (long[]) insn.getData();
long[] larray = (long[]) data;
for (long b : larray) {
str.append(TypeGen.literalToString(b, elType));
str.append(", ");
......@@ -494,7 +500,7 @@ public class InsnGen {
}
int len = str.length();
str.delete(len - 2, len);
code.add("new ").add(useType(elType)).add("[] { ").add(str.toString()).add(" }");
code.add("new ").add(useType(elType)).add("[]{").add(str.toString()).add('}');
}
private void makeConstructor(ConstructorInsn insn, CodeWriter code, EnumSet<IGState> state)
......
......@@ -4,18 +4,17 @@ import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.PrimitiveType;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction;
public class FillArrayNode extends InsnNode {
private final Object data;
private ArgType elemType;
public FillArrayNode(int resReg, FillArrayDataPayloadDecodedInstruction payload) {
super(InsnType.FILL_ARRAY, 0);
this.data = payload.getData();
ArgType elType;
switch (payload.getElementWidthUnit()) {
case 1:
......@@ -32,12 +31,26 @@ public class FillArrayNode extends InsnNode {
break;
default:
throw new AssertionError();
throw new JadxRuntimeException("Unknown array element width: " + payload.getElementWidthUnit());
}
setResult(InsnArg.reg(resReg, ArgType.array(elType)));
this.data = payload.getData();
this.elemType = elType;
}
public Object getData() {
return data;
}
public ArgType getElementType() {
return elemType;
}
public void mergeElementType(ArgType foundElemType) {
ArgType r = ArgType.merge(elemType, foundElemType);
if (r != null) {
elemType = r;
}
}
}
......@@ -339,7 +339,7 @@ public abstract class ArgType {
}
public static ArgType merge(ArgType a, ArgType b) {
if (a == b)
if (a.equals(b))
return a;
if (b == null || a == null)
......@@ -352,9 +352,9 @@ public abstract class ArgType {
}
private static ArgType mergeInternal(ArgType a, ArgType b) {
if (a == UNKNOWN)
if (a == UNKNOWN) {
return b;
}
if (!a.isTypeKnown()) {
if (b.isTypeKnown()) {
if (a.contains(b.getPrimitiveType()))
......@@ -399,10 +399,22 @@ public abstract class ArgType {
return (obj == null ? null : object(obj));
}
}
if (a.isArray() && b.isArray()) {
ArgType res = merge(a.getArrayElement(), b.getArrayElement());
if (a.isArray()) {
if (b.isArray()) {
ArgType ea = a.getArrayElement();
ArgType eb = b.getArrayElement();
if (ea.isPrimitive() && eb.isPrimitive()) {
return OBJECT;
} else {
ArgType res = merge(ea, eb);
return (res == null ? null : ArgType.array(res));
}
} else if (b.equals(OBJECT)) {
return OBJECT;
} else {
return null;
}
}
if (a.isPrimitive() && b.isPrimitive() && a.getRegCount() == b.getRegCount()) {
return primitive(PrimitiveType.getSmaller(a.getPrimitiveType(), b.getPrimitiveType()));
}
......
......@@ -5,6 +5,7 @@ import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.ConstClassNode;
import jadx.core.dex.instructions.ConstStringNode;
import jadx.core.dex.instructions.FillArrayNode;
import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.InvokeNode;
......@@ -164,6 +165,7 @@ 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());
remover.add(insn);
}
}
......
package jadx.core.utils;
import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.attributes.JadxErrorAttr;
import jadx.core.dex.nodes.ClassNode;
......@@ -40,6 +41,7 @@ public class ErrorsCounter {
}
node.getAttributes().add(new JadxErrorAttr(e));
} else {
node.getAttributes().add(AttributeFlag.INCONSISTENT_CODE);
LOG.error(msg);
}
}
......
......@@ -11,11 +11,13 @@ import org.junit.Before;
import org.junit.Test;
import static jadx.core.dex.instructions.args.ArgType.BOOLEAN;
import static jadx.core.dex.instructions.args.ArgType.BYTE;
import static jadx.core.dex.instructions.args.ArgType.CHAR;
import static jadx.core.dex.instructions.args.ArgType.INT;
import static jadx.core.dex.instructions.args.ArgType.LONG;
import static jadx.core.dex.instructions.args.ArgType.NARROW;
import static jadx.core.dex.instructions.args.ArgType.OBJECT;
import static jadx.core.dex.instructions.args.ArgType.STRING;
import static jadx.core.dex.instructions.args.ArgType.UNKNOWN;
import static jadx.core.dex.instructions.args.ArgType.UNKNOWN_OBJECT;
import static jadx.core.dex.instructions.args.ArgType.genericType;
......@@ -57,6 +59,13 @@ public class TypeMergeTest {
unknown(PrimitiveType.OBJECT, PrimitiveType.ARRAY),
unknown(PrimitiveType.OBJECT));
check(ArgType.array(INT), ArgType.array(BYTE), ArgType.OBJECT);
first(ArgType.array(INT), ArgType.array(INT));
first(ArgType.array(STRING), ArgType.array(STRING));
first(OBJECT, ArgType.array(INT));
first(OBJECT, ArgType.array(STRING));
ArgType objExc = object("java.lang.Exception");
ArgType objThr = object("java.lang.Throwable");
ArgType objIO = object("java.io.IOException");
......
......@@ -4,7 +4,7 @@ public class TestArrays extends AbstractTest {
public int test1(int i) {
// fill-array-data
int[] a = new int[] { 1, 2, 3, 5 };
int[] a = new int[]{1, 2, 3, 5};
return a[i];
}
......@@ -20,11 +20,27 @@ public class TestArrays extends AbstractTest {
return a.length;
}
private static Object test4(int type) {
if (type == 1) {
return new int[]{1, 2};
} else if (type == 2) {
return new float[]{1, 2};
} else if (type == 3) {
return new short[]{1, 2};
} else if (type == 4) {
return new byte[]{1, 2};
} else {
return null;
}
}
@Override
public boolean testRun() throws Exception {
assertEquals(test1(2), 3);
assertEquals(test2(2), 2);
assertEquals(test3(2), 2);
assertTrue(test4(4) instanceof byte[]);
return true;
}
......
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