core: fix type in fill-array instruction
This commit is contained in:
@@ -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,9 +399,21 @@ public abstract class ArgType {
|
||||
return (obj == null ? null : object(obj));
|
||||
}
|
||||
}
|
||||
if (a.isArray() && b.isArray()) {
|
||||
ArgType res = merge(a.getArrayElement(), b.getArrayElement());
|
||||
return (res == null ? null : ArgType.array(res));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user