Skip to content

Commit

Permalink
fix: correct type and data merge for filled-array instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Aug 23, 2020
1 parent 605a679 commit 89b4ae6
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 7 deletions.
10 changes: 9 additions & 1 deletion jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,16 @@ private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) thro
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

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);
Expand Down
53 changes: 53 additions & 0 deletions jadx-core/src/main/java/jadx/core/utils/EncodedValueUtils.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
7 changes: 2 additions & 5 deletions jadx-core/src/main/java/jadx/core/utils/InsnUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,8 @@ public static Object getConstValueByInsn(RootNode root, InsnNode insn) {
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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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, ");
}
}

0 comments on commit 89b4ae6

Please sign in to comment.