From bd1c3fffde556a8c280fa6e69b259c9196571e38 Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:32:14 +0100 Subject: [PATCH] fix: improve handler path check for regions --- .../regions/ProcessTryCatchRegions.java | 4 +- .../java/jadx/core/utils/RegionUtils.java | 40 +++++++++++++++---- .../trycatch/TestTryCatchFinally8.java | 24 +++++------ 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java index 10df6e2c9..cef7121c1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java @@ -117,12 +117,12 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { return true; } - private static boolean isHandlerPath(TryCatchBlockAttr tb, IContainer cont) { + private static boolean isHandlerPath(TryCatchBlockAttr tb, IContainer container) { for (ExceptionHandler h : tb.getHandlers()) { BlockNode handlerBlock = h.getHandlerBlock(); if (handlerBlock != null && !handlerBlock.contains(AFlag.REMOVE) - && RegionUtils.hasPathThroughBlock(handlerBlock, cont)) { + && RegionUtils.isPathExists(handlerBlock, container)) { return true; } } diff --git a/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java b/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java index 267bcb9cf..576bcc707 100644 --- a/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java @@ -25,6 +25,8 @@ import jadx.core.dex.nodes.IRegion; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.regions.Region; +import jadx.core.dex.regions.SwitchRegion; +import jadx.core.dex.regions.TryCatchRegion; import jadx.core.dex.regions.loops.LoopRegion; import jadx.core.dex.trycatch.CatchAttr; import jadx.core.dex.trycatch.ExceptionHandler; @@ -109,19 +111,31 @@ public class RegionUtils { } return null; } - if (container instanceof IBranchRegion) { - return null; + if (container instanceof IConditionRegion) { + return ListUtils.firstOrNull(((IConditionRegion) container).getConditionBlocks()); + } + if (container instanceof TryCatchRegion) { + return getFirstBlockNode(((TryCatchRegion) container).getTryRegion()); + } + if (container instanceof SwitchRegion) { + return ((SwitchRegion) container).getHeader(); } if (container instanceof IRegion) { - List blocks = ((IRegion) container).getSubBlocks(); - if (blocks.isEmpty()) { - return null; - } - return getFirstBlockNode(blocks.get(0)); + return getFirstBlockNode(((IRegion) container).getSubBlocks()); } throw new JadxRuntimeException(unknownContainerType(container)); } + private static @Nullable BlockNode getFirstBlockNode(List containers) { + for (IContainer cont : containers) { + BlockNode firstBlockNode = getFirstBlockNode(cont); + if (firstBlockNode != null) { + return firstBlockNode; + } + } + return null; + } + public static int getFirstSourceLine(IContainer container) { if (container instanceof IBlock) { return BlockUtils.getFirstSourceLine((IBlock) container); @@ -586,6 +600,18 @@ public class RegionUtils { throw new JadxRuntimeException(unknownContainerType(cont)); } + /** + * Check if path exists from block to container start. + * Return false if block is inside container. + */ + public static boolean isPathExists(BlockNode block, IContainer container) { + BlockNode firstBlock = RegionUtils.getFirstBlockNode(container); + if (firstBlock != null) { + return BlockUtils.isPathExists(block, firstBlock); + } + return false; + } + protected static String unknownContainerType(IContainer container) { if (container == null) { return "Null container variable"; diff --git a/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally8.java b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally8.java index f578ff163..5fd38491a 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally8.java +++ b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally8.java @@ -8,10 +8,12 @@ import org.junit.jupiter.api.Test; import jadx.NotYetImplemented; import jadx.tests.api.IntegrationTest; -import jadx.tests.api.utils.assertj.JadxAssertions; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestTryCatchFinally8 extends IntegrationTest { + @SuppressWarnings({ "ResultOfMethodCallIgnored", "TryFinallyCanBeTryWithResources", "DataFlowIssue" }) public static class TestCls { public Object test(Object obj) { File file = new File("r"); @@ -42,20 +44,12 @@ public class TestTryCatchFinally8 extends IntegrationTest { @Test @NotYetImplemented("Fix merged catch blocks (shared code between catches)") public void test() { - JadxAssertions.assertThat(getClassNode(TestCls.class)) + assertThat(getClassNode(TestCls.class)) .code() - .contains("try {") - .contains("} catch (IOException e) {") - .contains("} finally {") - .contains("file.delete();"); - } - - @Test - public void test2() { - disableCompilation(); - JadxAssertions.assertThat(getClassNode(TestCls.class)) - .code() - .contains("output = new FileOutputStream(file);") - .contains("} catch (IOException e) {"); + .containsOne("FileOutputStream output = null;") + .countString(2, "try {") + .countString(2, "} catch (IOException e") + .containsOne("} finally {") + .containsOne("file.delete();"); } }