From e7598d434005e4482aa9d0ac68feb453677e02be Mon Sep 17 00:00:00 2001 From: Skylot Date: Thu, 3 Dec 2020 18:28:25 +0000 Subject: [PATCH] fix: don't add region on exit block (#1040) --- .../dex/visitors/regions/RegionMaker.java | 26 ++++++++++++ .../trycatch/TestLoopInTryCatch.java | 29 +++++++++++++ .../smali/trycatch/TestLoopInTryCatch.smali | 42 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/trycatch/TestLoopInTryCatch.java create mode 100644 jadx-core/src/test/smali/trycatch/TestLoopInTryCatch.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 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