提交 bd4c61d3 编写于 作者: S Skylot

core: fix incorrect float values processing

上级 00a6b6ef
...@@ -41,10 +41,11 @@ public class TypeGen { ...@@ -41,10 +41,11 @@ public class TypeGen {
public static String literalToString(long lit, ArgType type) { public static String literalToString(long lit, ArgType type) {
if (type == null || !type.isTypeKnown()) { if (type == null || !type.isTypeKnown()) {
String n = Long.toString(lit); String n = Long.toString(lit);
if (Math.abs(lit) > 100) if (Math.abs(lit) > 100) {
n += "; // 0x" + Long.toHexString(lit) n += "; // 0x" + Long.toHexString(lit)
+ " float:" + Float.intBitsToFloat((int) lit) + " float:" + Float.intBitsToFloat((int) lit)
+ " double:" + Double.longBitsToDouble(lit); + " double:" + Double.longBitsToDouble(lit);
}
return n; return n;
} }
......
...@@ -40,6 +40,10 @@ public abstract class ArgType { ...@@ -40,6 +40,10 @@ public abstract class ArgType {
PrimitiveType.BOOLEAN, PrimitiveType.SHORT, PrimitiveType.BYTE, PrimitiveType.CHAR, PrimitiveType.BOOLEAN, PrimitiveType.SHORT, PrimitiveType.BYTE, PrimitiveType.CHAR,
PrimitiveType.OBJECT, PrimitiveType.ARRAY); PrimitiveType.OBJECT, PrimitiveType.ARRAY);
public static final ArgType NARROW_NUMBERS = unknown(
PrimitiveType.INT, PrimitiveType.FLOAT,
PrimitiveType.BOOLEAN, PrimitiveType.SHORT, PrimitiveType.BYTE, PrimitiveType.CHAR);
public static final ArgType WIDE = unknown(PrimitiveType.LONG, PrimitiveType.DOUBLE); public static final ArgType WIDE = unknown(PrimitiveType.LONG, PrimitiveType.DOUBLE);
protected int hash; protected int hash;
...@@ -597,8 +601,14 @@ public abstract class ArgType { ...@@ -597,8 +601,14 @@ public abstract class ArgType {
public int getRegCount() { public int getRegCount() {
if (isPrimitive()) { if (isPrimitive()) {
PrimitiveType type = getPrimitiveType(); PrimitiveType type = getPrimitiveType();
if (type == PrimitiveType.LONG || type == PrimitiveType.DOUBLE) if (type == PrimitiveType.LONG || type == PrimitiveType.DOUBLE) {
return 2; return 2;
} else {
return 1;
}
}
if (!isTypeKnown()) {
return 0;
} }
return 1; return 1;
} }
......
...@@ -8,10 +8,20 @@ public final class LiteralArg extends InsnArg { ...@@ -8,10 +8,20 @@ public final class LiteralArg extends InsnArg {
private final long literal; private final long literal;
public LiteralArg(long value, ArgType type) { public LiteralArg(long value, ArgType type) {
if (value != 0) {
if (type.isObject()) {
throw new JadxRuntimeException("Wrong literal type: " + type + " for value: " + value);
} else if (!type.isTypeKnown()
&& !type.contains(PrimitiveType.LONG)
&& !type.contains(PrimitiveType.DOUBLE)) {
ArgType m = ArgType.merge(type, ArgType.NARROW_NUMBERS);
if (m != null) {
type = m;
}
}
}
this.literal = value; this.literal = value;
this.typedVar = new TypedVar(type); this.typedVar = new TypedVar(type);
if (literal != 0 && type.isObject())
throw new RuntimeException("wrong literal type");
} }
public long getLiteral() { public long getLiteral() {
......
...@@ -37,8 +37,12 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -37,8 +37,12 @@ public class ConstInlinerVisitor extends AbstractVisitor {
private static boolean checkInsn(MethodNode mth, BlockNode block, InsnNode insn) { private static boolean checkInsn(MethodNode mth, BlockNode block, InsnNode insn) {
if (insn.getType() == InsnType.CONST) { if (insn.getType() == InsnType.CONST) {
InsnArg arg = insn.getArg(0); InsnArg arg = insn.getArg(0);
if (arg.isLiteral() if (arg.isLiteral()) {
&& insn.getResult().getType().getRegCount() == 1 /* process only narrow types */) { ArgType resType = insn.getResult().getType();
// make sure arg has correct type
if (!arg.getType().isTypeKnown()) {
arg.merge(resType);
}
long lit = ((LiteralArg) arg).getLiteral(); long lit = ((LiteralArg) arg).getLiteral();
return replaceConst(mth, block, insn, lit); return replaceConst(mth, block, insn, lit);
} }
...@@ -61,17 +65,9 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -61,17 +65,9 @@ public class ConstInlinerVisitor extends AbstractVisitor {
if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) { if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) {
// in most cases type not equal arg.getType() // in most cases type not equal arg.getType()
// just set unknown type and run type fixer // just set unknown type and run type fixer
LiteralArg litArg = InsnArg.lit(literal, ArgType.NARROW); LiteralArg litArg = InsnArg.lit(literal, ArgType.UNKNOWN);
if (useInsn.replaceArg(arg, litArg)) { if (useInsn.replaceArg(arg, litArg)) {
// if (useInsn.getType() == InsnType.MOVE) { fixTypes(mth, useInsn, litArg);
// // 'move' became 'const'
// InsnNode constInsn = new InsnNode(mth, InsnType.CONST, 1);
// constInsn.setResult(useInsn.getResult());
// constInsn.addArg(litArg);
// ModVisitor.replaceInsn(useBlock, useInsn, constInsn);
// fixTypes(mth, constInsn);
// }
fixTypes(mth, useInsn);
replace++; replace++;
} }
} }
...@@ -102,7 +98,7 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -102,7 +98,7 @@ public class ConstInlinerVisitor extends AbstractVisitor {
* This is method similar to PostTypeResolver.visit method, * This is method similar to PostTypeResolver.visit method,
* but contains some expensive operations needed only after constant inline * but contains some expensive operations needed only after constant inline
*/ */
private static void fixTypes(MethodNode mth, InsnNode insn) { private static void fixTypes(MethodNode mth, InsnNode insn, LiteralArg litArg) {
switch (insn.getType()) { switch (insn.getType()) {
case CONST: case CONST:
insn.getArg(0).merge(insn.getResult()); insn.getArg(0).merge(insn.getResult());
...@@ -120,13 +116,30 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -120,13 +116,30 @@ public class ConstInlinerVisitor extends AbstractVisitor {
break; break;
} }
case IF: case IF: {
IfNode ifnode = (IfNode) insn; IfNode ifnode = (IfNode) insn;
if (!ifnode.isZeroCmp()) { if (!ifnode.isZeroCmp()) {
insn.getArg(1).merge(insn.getArg(0)); InsnArg arg0 = insn.getArg(0);
insn.getArg(0).merge(insn.getArg(1)); InsnArg arg1 = insn.getArg(1);
if (arg0 == litArg) {
arg0.merge(arg1);
} else {
arg1.merge(arg0);
}
} }
break; break;
}
case CMP_G:
case CMP_L: {
InsnArg arg0 = insn.getArg(0);
InsnArg arg1 = insn.getArg(1);
if (arg0 == litArg) {
arg0.merge(arg1);
} else {
arg1.merge(arg0);
}
break;
}
case RETURN: case RETURN:
if (insn.getArgsCount() != 0) { if (insn.getArgsCount() != 0) {
...@@ -153,6 +166,21 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -153,6 +166,21 @@ public class ConstInlinerVisitor extends AbstractVisitor {
} }
break; break;
case ARITH:
litArg.merge(insn.getResult());
break;
case APUT:
case AGET:
if (litArg == insn.getArg(1)) {
litArg.merge(ArgType.INT);
}
break;
case NEW_ARRAY:
litArg.merge(ArgType.INT);
break;
default: default:
break; break;
} }
......
package jadx.tests.internal;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
public class TestArgInline extends InternalJadxTest {
public static class TestCls {
public void method(int a) {
while (a < 10) {
int b = a + 1;
a = b;
}
}
}
//@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, not(containsString("a = a + 1;")));
assertThat(code, containsString("a++;"));
}
}
package jadx.tests.internal;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
public class TestFloatValue extends InternalJadxTest {
public static class TestCls {
public float[] method() {
float[] fa = {0.55f};
fa[0] /= 2;
return fa;
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, not(containsString("1073741824")));
assertThat(code, containsString("0.55f;"));
assertThat(code, containsString("fa[0] = fa[0] / 2.0f;"));
}
}
package jadx.tests.internal;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.visitors.DepthTraverser;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.DecodeException;
import java.util.List;
import org.slf4j.Logger;
public class TestVariablesDefinitions extends InternalJadxTest {
public static class TestCls {
private static Logger LOG;
private ClassNode cls;
private List<IDexTreeVisitor> passes;
public void run() {
try {
cls.load();
for (IDexTreeVisitor visitor : passes) {
DepthTraverser.visit(visitor, cls);
}
} catch (DecodeException e) {
LOG.error("Decode exception: " + cls, e);
} finally {
cls.unload();
}
}
}
//@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册