From 7a5a2fcd8495d16ec1c3ac98aaf82d25b6638cb0 Mon Sep 17 00:00:00 2001 From: xxjy Date: Thu, 10 Feb 2022 04:55:15 +0800 Subject: [PATCH] fix: nested try catches with overlap try blocks (#1374)(PR #1375) * fix: nested try catch decompilation failed (#1374) * add tests and sort handlers Co-authored-by: Skylot --- .../jadx/core/dex/trycatch/CatchAttr.java | 8 +++- .../dex/visitors/AttachTryCatchVisitor.java | 4 +- .../blocks/BlockExceptionHandler.java | 2 +- .../trycatch/TestNestedTryCatch2.java | 38 +++++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/trycatch/TestNestedTryCatch2.java diff --git a/jadx-core/src/main/java/jadx/core/dex/trycatch/CatchAttr.java b/jadx-core/src/main/java/jadx/core/dex/trycatch/CatchAttr.java index 6dfc1b4c8..0a85670e1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/trycatch/CatchAttr.java +++ b/jadx-core/src/main/java/jadx/core/dex/trycatch/CatchAttr.java @@ -1,5 +1,6 @@ package jadx.core.dex.trycatch; +import java.util.Comparator; import java.util.List; import jadx.api.plugins.input.data.attributes.IJadxAttribute; @@ -8,9 +9,14 @@ import jadx.core.utils.Utils; public class CatchAttr implements IJadxAttribute { + public static CatchAttr build(List handlers) { + handlers.sort(Comparator.comparingInt(ExceptionHandler::getHandlerOffset)); + return new CatchAttr(handlers); + } + private final List handlers; - public CatchAttr(List handlers) { + private CatchAttr(List handlers) { this.handlers = handlers; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/AttachTryCatchVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/AttachTryCatchVisitor.java index d3060b5db..016dca680 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/AttachTryCatchVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/AttachTryCatchVisitor.java @@ -55,7 +55,7 @@ public class AttachTryCatchVisitor extends AbstractVisitor { if (handlers.isEmpty()) { continue; } - markTryBounds(insnByOffset, tryData, new CatchAttr(handlers)); + markTryBounds(insnByOffset, tryData, CatchAttr.build(handlers)); } } @@ -96,7 +96,7 @@ public class AttachTryCatchVisitor extends AbstractVisitor { if (existAttr != null) { // merge handlers List handlers = Utils.concat(existAttr.getHandlers(), catchAttr.getHandlers()); - insn.addAttr(new CatchAttr(handlers)); + insn.addAttr(CatchAttr.build(handlers)); } else { insn.addAttr(catchAttr); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java b/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java index 9f8c3961c..8e7b5fbca 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java @@ -126,7 +126,7 @@ public class BlockExceptionHandler { commonCatchAttr = catchAttr; continue; } - if (commonCatchAttr != catchAttr) { + if (!commonCatchAttr.equals(catchAttr)) { return null; } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestNestedTryCatch2.java b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestNestedTryCatch2.java new file mode 100644 index 000000000..a80e32419 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestNestedTryCatch2.java @@ -0,0 +1,38 @@ +package jadx.tests.integration.trycatch; + +import jadx.tests.api.IntegrationTest; +import jadx.tests.api.extensions.profiles.TestProfile; +import jadx.tests.api.extensions.profiles.TestWithProfiles; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestNestedTryCatch2 extends IntegrationTest { + + public static class TestCls { + public void test() { + try { + try { + call(); + call(); + } catch (Exception e) { + exc(e); + } + } catch (Exception e) { + exc(e); + } + } + + private void call() { + } + + private void exc(Exception e) { + } + } + + @TestWithProfiles({ TestProfile.JAVA8, TestProfile.DX_J8 }) + public void test() { + assertThat(getClassNode(TestCls.class)) + .code() + .countString(2, "} catch (Exception "); + } +}