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 1e6eae740..0110311b9 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 @@ -30,6 +30,7 @@ import jadx.core.dex.nodes.Edge; import jadx.core.dex.nodes.IBlock; import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IRegion; +import jadx.core.dex.nodes.InsnContainer; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.regions.Region; @@ -76,6 +77,10 @@ public class RegionMaker { if (startBlock == null) { return r; } + if (stack.containsExit(startBlock)) { + insertEdgeInsns(r, startBlock); + return r; + } int startBlockId = startBlock.getId(); if (processedBlocks.get(startBlockId)) { @@ -95,6 +100,27 @@ public class RegionMaker { return r; } + private void insertEdgeInsns(Region region, BlockNode exitBlock) { + List edgeInsns = exitBlock.getAll(AType.EDGE_INSN); + if (edgeInsns.isEmpty()) { + return; + } + List insns = new ArrayList<>(edgeInsns.size()); + addOneInsnOfType(insns, edgeInsns, InsnType.BREAK); + addOneInsnOfType(insns, edgeInsns, InsnType.CONTINUE); + region.add(new InsnContainer(insns)); + } + + private void addOneInsnOfType(List insns, List edgeInsns, InsnType insnType) { + for (EdgeInsnAttr edgeInsn : edgeInsns) { + InsnNode insn = edgeInsn.getInsn(); + if (insn.getType() == insnType) { + insns.add(insn); + return; + } + } + } + /** * Recursively traverse all blocks from 'block' until block from 'exits' */ diff --git a/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestLoopInTryCatch.java b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestLoopInTryCatch.java new file mode 100644 index 000000000..cd17c91c6 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestLoopInTryCatch.java @@ -0,0 +1,29 @@ +package jadx.tests.integration.trycatch; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.SmaliTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestLoopInTryCatch extends SmaliTest { + @Test + public void test() { + assertThat(getClassNodeFromSmali()) + .code() + .containsLines(2, + "int i;", + "while (true) {", + " try {", + " i = getI();", + " } catch (RuntimeException unused) {", + " return;", + " }", + " if (i == 1 || i == 2) {", + " break;", + " }", + "}", + "if (i == 1) {", + "}"); + } +} diff --git a/jadx-core/src/test/smali/trycatch/TestLoopInTryCatch.smali b/jadx-core/src/test/smali/trycatch/TestLoopInTryCatch.smali new file mode 100644 index 000000000..132155ba7 --- /dev/null +++ b/jadx-core/src/test/smali/trycatch/TestLoopInTryCatch.smali @@ -0,0 +1,42 @@ +.class public Ltrycatch/TestLoopInTryCatch; +.super Ljava/lang/Object; +.source "SourceFile" + +.method public static test()V + .registers 6 + + :try_start + + :loop + + invoke-static {}, Ltrycatch/TestLoopInTryCatch;->getI()I + move-result v1 + + const/4 v2, 0x1 + + if-eq v1, v2, :cond + + const/4 v3, 0x2 + + if-eq v1, v3, :cond + + goto :loop + + :cond + if-eq v1, v2, :end + + return-void + + :try_end + .catch Ljava/lang/RuntimeException; {:try_start .. :try_end} :end + + :end + return-void +.end method + +.method public static getI()I + .locals 2 + + const/4 v1, 0x1 + return v1 +.end method