From 8de6190a818d153b4cb52dd07f5901ce2bdb21af Mon Sep 17 00:00:00 2001 From: Skylot Date: Wed, 17 Dec 2014 23:14:03 +0300 Subject: [PATCH] core: fix type inference for arguments in Phi node (fix #33) --- .../typeinference/PostTypeInference.java | 34 ++++++++++++----- .../integration/types/TestTypeResolver3.java | 38 +++++++++++++++++++ 2 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver3.java diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java index 4e026df38..468cf9d9b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java @@ -8,7 +8,6 @@ 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.instructions.args.RegisterArg; -import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; @@ -100,18 +99,26 @@ public class PostTypeInference { case PHI: { PhiInsn phi = (PhiInsn) insn; - RegisterArg result = phi.getResult(); - SSAVar resultSVar = result.getSVar(); - if (resultSVar != null && !result.getType().isTypeKnown()) { + ArgType type = phi.getResult().getType(); + if (!type.isTypeKnown()) { for (InsnArg arg : phi.getArguments()) { - ArgType argType = arg.getType(); - if (argType.isTypeKnown()) { - resultSVar.setType(argType); - return true; + if (arg.getType().isTypeKnown()) { + type = arg.getType(); + break; } } } - return false; + boolean changed = false; + if (updateType(phi.getResult(), type)) { + changed = true; + } + for (int i = 0; i < phi.getArgsCount(); i++) { + RegisterArg arg = phi.getArg(i); + if (updateType(arg, type)) { + changed = true; + } + } + return changed; } default: @@ -120,6 +127,15 @@ public class PostTypeInference { return false; } + private static boolean updateType(RegisterArg arg, ArgType type) { + ArgType prevType = arg.getType(); + if (prevType == null || !prevType.equals(type)) { + arg.setType(type); + return true; + } + return false; + } + private static boolean fixArrayTypes(InsnArg array, InsnArg elem) { boolean change = false; if (!elem.getType().isTypeKnown() && elem.merge(array.getType().getArrayElement())) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver3.java b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver3.java new file mode 100644 index 000000000..ba54a58db --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver3.java @@ -0,0 +1,38 @@ +package jadx.tests.integration.types; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.junit.Assert.assertThat; + +public class TestTypeResolver3 extends IntegrationTest { + + public static class TestCls { + + public int test(String s1, String s2) { + int cmp = s2.compareTo(s1); + if (cmp != 0) { + return cmp; + } + return s1.length() == s2.length() ? 0 : s1.length() < s2.length() ? -1 : 1; + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + // TODO inline into return + assertThat(code, containsOne("s1.length() == s2.length() ? 0 : s1.length() < s2.length() ? -1 : 1;")); + } + + @Test + public void test2() { + noDebugInfo(); + getClassNode(TestCls.class); + } +}