From 2b9c09270527d4154b08060d8ab94ca1c77e2f57 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sat, 1 Aug 2015 21:57:30 +0300 Subject: [PATCH] core: fix field initialization extract from try/catch block (fix #78) --- .../java/jadx/core/dex/nodes/InsnNode.java | 15 ++++ .../core/dex/visitors/ExtractFieldInit.java | 22 +++-- .../others/TestFieldInitInTryCatch.java | 87 +++++++++++++++++++ 3 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitInTryCatch.java diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java index b3d93864..7878d0b3 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java @@ -205,6 +205,21 @@ public class InsnNode extends LineAttrNode { } } + public boolean canReorderRecursive() { + if (!canReorder()) { + return false; + } + for (InsnArg arg : this.getArguments()) { + if (arg.isInsnWrap()) { + InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); + if (!wrapInsn.canReorderRecursive()) { + return false; + } + } + } + return true; + } + @Override public String toString() { return InsnUtils.formatOffset(offset) + ": " diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java index 0d293e34..6608f657 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java @@ -6,6 +6,8 @@ import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.FieldInfo; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; +import jadx.core.dex.instructions.args.InsnArg; +import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.ClassNode; @@ -189,14 +191,22 @@ public class ExtractFieldInit extends AbstractVisitor { } private static boolean checkInsn(InsnNode insn) { + InsnArg arg = insn.getArg(0); + if (arg.isInsnWrap()) { + InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); + if (!wrapInsn.canReorderRecursive() && insn.contains(AType.CATCH_BLOCK)) { + return false; + } + } else { + return arg.isLiteral() || arg.isThis(); + } Set regs = new HashSet(); insn.getRegisterArgs(regs); - if (regs.isEmpty()) { - return true; - } - for (RegisterArg reg : regs) { - if (!reg.isThis()) { - return false; + if (!regs.isEmpty()) { + for (RegisterArg reg : regs) { + if (!reg.isThis()) { + return false; + } } } return true; diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitInTryCatch.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitInTryCatch.java new file mode 100644 index 00000000..046a7a9a --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitInTryCatch.java @@ -0,0 +1,87 @@ +package jadx.tests.integration.others; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsLines; +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.junit.Assert.assertThat; + +public class TestFieldInitInTryCatch extends IntegrationTest { + + public static class TestCls { + private static final URL a; + + static { + try { + a = new URL("http://www.example.com/"); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + public static class TestCls2 { + private static final URL[] a; + + static { + try { + a = new URL[]{new URL("http://www.example.com/")}; + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + public static class TestCls3 { + private static final String[] a; + + static { + try { + a = new String[]{"a"}; + // Note: follow code will not be extracted: + // a = new String[]{new String("a")}; + new URL("http://www.example.com/"); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("private static final URL a;")); + assertThat(code, containsOne("a = new URL(\"http://www.example.com/\");")); + assertThat(code, containsLines(2, + "try {", + indent(1) + "a = new URL(\"http://www.example.com/\");", + "} catch (MalformedURLException e) {")); + } + + @Test + public void test2() { + ClassNode cls = getClassNode(TestCls2.class); + String code = cls.getCode().toString(); + + assertThat(code, containsLines(2, + "try {", + indent(1) + "a = new URL[]{new URL(\"http://www.example.com/\")};", + "} catch (MalformedURLException e) {")); + } + + @Test + public void test3() { + ClassNode cls = getClassNode(TestCls3.class); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("private static final String[] a = new String[]{\"a\"};")); + } +} -- GitLab