From 3f25f072c63ef13178c79f2f5819e82629120738 Mon Sep 17 00:00:00 2001 From: Jonas Konrad Date: Thu, 3 Dec 2020 15:15:49 +0100 Subject: [PATCH] fix: properly traverse methods with synchronize blocks that have no clear exit (PR #1041) --- .../dex/visitors/regions/RegionMaker.java | 2 + .../loops/TestSynchronizedInEndlessLoop.java | 2 - .../synchronize/TestSynchronized5.java | 20 ++++++ .../smali/synchronize/TestSynchronized5.smali | 62 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized5.java create mode 100644 jadx-core/src/test/smali/synchronize/TestSynchronized5.smali diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index b937cc33..0622d212 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -594,6 +594,8 @@ public class RegionMaker { List list = BlockUtils.buildSimplePath(exitBlock); if (list.isEmpty() || !list.get(list.size() - 1).getSuccessors().isEmpty()) { stack.addExit(exitBlock); + // we can still try using this as an exit block to make sure it's visited. + exit = exitBlock; } } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/loops/TestSynchronizedInEndlessLoop.java b/jadx-core/src/test/java/jadx/tests/integration/loops/TestSynchronizedInEndlessLoop.java index 0c574aaf..13f9c760 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/loops/TestSynchronizedInEndlessLoop.java +++ b/jadx-core/src/test/java/jadx/tests/integration/loops/TestSynchronizedInEndlessLoop.java @@ -2,7 +2,6 @@ package jadx.tests.integration.loops; import org.junit.jupiter.api.Test; -import jadx.NotYetImplemented; import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.IntegrationTest; @@ -34,7 +33,6 @@ public class TestSynchronizedInEndlessLoop extends IntegrationTest { } @Test - @NotYetImplemented public void test() { ClassNode cls = getClassNode(TestCls.class); String code = cls.getCode().toString(); diff --git a/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized5.java b/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized5.java new file mode 100644 index 00000000..2a918bcb --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized5.java @@ -0,0 +1,20 @@ +package jadx.tests.integration.synchronize; + +import org.junit.jupiter.api.Test; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.SmaliTest; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +public class TestSynchronized5 extends SmaliTest { + @Test + public void test() { + ClassNode cls = getClassNodeFromSmali(); + String code = cls.getCode().toString(); + + assertThat(code, containsString("1 != 0")); + assertThat(code, containsString("System.gc();")); + } +} diff --git a/jadx-core/src/test/smali/synchronize/TestSynchronized5.smali b/jadx-core/src/test/smali/synchronize/TestSynchronized5.smali new file mode 100644 index 00000000..cdc2056f --- /dev/null +++ b/jadx-core/src/test/smali/synchronize/TestSynchronized5.smali @@ -0,0 +1,62 @@ +.class public Lsynchronize/TestSynchronized5; +.super Ljava/lang/Object; + +.method public final get()V + .registers 6 + + monitor-enter p0 + + :try_start_1 + + const/4 v0, 0 + + if-eqz v0, :cond_1 + + monitor-exit p0 + + return-void + + :cond_1 + + monitor-exit p0 + :try_end_1 + .catchall {:try_start_1 .. :try_end_1} :catchall_1 + + monitor-enter p0 + + :try_start_2 + + const/4 v1, 1 + + if-eqz v1, :cond_2 + + invoke-static {}, Ljava/lang/System;->gc()V + + :cond_2 + + monitor-exit p0 + :try_end_2 + .catchall {:try_start_2 .. :try_end_2} :catchall_2 + + return-void + + :catchall_2 + move-exception v0 + + :try_start_3 + monitor-exit p0 + :try_end_3 + .catchall {:try_start_3 .. :try_end_3} :catchall_2 + + throw v0 + + :catchall_1 + move-exception v0 + + :try_start_4 + monitor-exit p0 + :try_end_4 + .catchall {:try_start_4 .. :try_end_4} :catchall_1 + + throw v0 +.end method -- GitLab