fix: correct type and data merge for filled-array instruction
This commit is contained in:
@@ -569,8 +569,16 @@ public class InsnGen {
|
||||
private void fillArray(CodeWriter code, FillArrayInsn arrayNode) throws CodegenException {
|
||||
code.add("// fill-array-data instruction");
|
||||
code.startLine();
|
||||
List<LiteralArg> args = arrayNode.getLiteralArgs(arrayNode.getElementType());
|
||||
InsnArg arrArg = arrayNode.getArg(0);
|
||||
ArgType arrayType = arrArg.getType();
|
||||
ArgType elemType;
|
||||
if (arrayType.isTypeKnown() && arrayType.isArray()) {
|
||||
elemType = arrayType.getArrayElement();
|
||||
} else {
|
||||
ArgType elementType = arrayNode.getElementType(); // unknown type
|
||||
elemType = elementType.selectFirst();
|
||||
}
|
||||
List<LiteralArg> args = arrayNode.getLiteralArgs(elemType);
|
||||
int len = args.size();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public final class FillArrayData extends InsnNode {
|
||||
|
||||
private static final ArgType ONE_BYTE_TYPE = ArgType.unknown(PrimitiveType.BOOLEAN, PrimitiveType.BYTE);
|
||||
private static final ArgType ONE_BYTE_TYPE = ArgType.unknown(PrimitiveType.BYTE, PrimitiveType.BOOLEAN);
|
||||
private static final ArgType TWO_BYTES_TYPE = ArgType.unknown(PrimitiveType.SHORT, PrimitiveType.CHAR);
|
||||
private static final ArgType FOUR_BYTES_TYPE = ArgType.unknown(PrimitiveType.INT, PrimitiveType.FLOAT);
|
||||
private static final ArgType EIGHT_BYTES_TYPE = ArgType.unknown(PrimitiveType.LONG, PrimitiveType.DOUBLE);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package jadx.core.utils;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.api.plugins.input.data.annotations.EncodedValue;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.LiteralArg;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
|
||||
public class EncodedValueUtils {
|
||||
|
||||
/**
|
||||
* Return constant literal from {@code jadx.api.plugins.input.data.annotations.EncodedValue}
|
||||
*
|
||||
* @return LiteralArg, String, ArgType or null
|
||||
*/
|
||||
@Nullable
|
||||
public static Object convertToConstValue(RootNode root, EncodedValue encodedValue) {
|
||||
if (encodedValue == null) {
|
||||
return null;
|
||||
}
|
||||
Object value = encodedValue.getValue();
|
||||
switch (encodedValue.getType()) {
|
||||
case ENCODED_NULL:
|
||||
return InsnArg.lit(0, ArgType.OBJECT);
|
||||
case ENCODED_BOOLEAN:
|
||||
return Boolean.TRUE.equals(value) ? LiteralArg.TRUE : LiteralArg.FALSE;
|
||||
case ENCODED_BYTE:
|
||||
return InsnArg.lit((Byte) value, ArgType.BYTE);
|
||||
case ENCODED_SHORT:
|
||||
return InsnArg.lit((Short) value, ArgType.SHORT);
|
||||
case ENCODED_CHAR:
|
||||
return InsnArg.lit((Character) value, ArgType.CHAR);
|
||||
case ENCODED_INT:
|
||||
return InsnArg.lit((Integer) value, ArgType.INT);
|
||||
case ENCODED_LONG:
|
||||
return InsnArg.lit((Long) value, ArgType.LONG);
|
||||
case ENCODED_FLOAT:
|
||||
return InsnArg.lit(Float.floatToIntBits((Float) value), ArgType.FLOAT);
|
||||
case ENCODED_DOUBLE:
|
||||
return InsnArg.lit(Double.doubleToLongBits((Double) value), ArgType.DOUBLE);
|
||||
case ENCODED_STRING:
|
||||
return (String) value;
|
||||
|
||||
case ENCODED_TYPE:
|
||||
return ArgType.parse((String) value);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,11 +101,8 @@ public class InsnUtils {
|
||||
return null;
|
||||
}
|
||||
FieldInitAttr attr = fieldNode.get(AType.FIELD_INIT);
|
||||
if (attr != null) {
|
||||
if (attr.getValueType() == FieldInitAttr.InitType.CONST) {
|
||||
return attr.getEncodedValue().getValue();
|
||||
}
|
||||
return attr.getInsn();
|
||||
if (attr != null && attr.getValueType() == FieldInitAttr.InitType.CONST) {
|
||||
return EncodedValueUtils.convertToConstValue(root, attr.getEncodedValue());
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package jadx.tests.integration.arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestArrayFill4 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
// replaced constant break filled array creation
|
||||
private static final int ARRAY_SIZE = 4;
|
||||
|
||||
public long[] test() {
|
||||
return new long[] { 0, 1, Long.MAX_VALUE, Long.MIN_VALUE + 1 };
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
noDebugInfo();
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code()
|
||||
.doesNotContain("new long[ARRAY_SIZE];")
|
||||
.containsOne("return new long[]{0, 1, ");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user