From 3ae8359408de8f20d65e0a77420a0df32c6a08b3 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 22 Jul 2019 18:24:43 +0300 Subject: [PATCH] fix: improve exception handler remove (#703) --- .../java/jadx/core/dex/nodes/MethodNode.java | 16 +++++++++------- .../core/dex/trycatch/ExceptionHandler.java | 10 ++++++++++ .../jadx/core/dex/trycatch/TryCatchBlock.java | 18 +++++++++++++++++- .../core/dex/visitors/MarkFinallyVisitor.java | 3 +++ .../java/jadx/core/utils/files/FileUtils.java | 10 ++++++++++ .../test/java/jadx/tests/external/.gitignore | 1 + 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 8ad22bc66..4f62faf6a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -303,13 +303,11 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode { // resolve nested try blocks: // inner block contains all handlers from outer block => remove these handlers from inner block // each handler must be only in one try/catch block - for (TryCatchBlock ct1 : catches) { - for (TryCatchBlock ct2 : catches) { - if (ct1 != ct2 && ct2.containsAllHandlers(ct1)) { - for (ExceptionHandler h : ct1.getHandlers()) { - ct2.removeHandler(mth, h); - h.setTryBlock(ct1); - } + for (TryCatchBlock outerTry : catches) { + for (TryCatchBlock innerTry : catches) { + if (outerTry != innerTry + && innerTry.containsAllHandlers(outerTry)) { + innerTry.removeSameHandlers(outerTry); } } } @@ -522,6 +520,10 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode { return handler; } + public boolean clearExceptionHandlers() { + return exceptionHandlers.removeIf(ExceptionHandler::isRemoved); + } + public Iterable getExceptionHandlers() { return exceptionHandlers; } diff --git a/jadx-core/src/main/java/jadx/core/dex/trycatch/ExceptionHandler.java b/jadx-core/src/main/java/jadx/core/dex/trycatch/ExceptionHandler.java index 4da8cc396..1eb086350 100644 --- a/jadx-core/src/main/java/jadx/core/dex/trycatch/ExceptionHandler.java +++ b/jadx-core/src/main/java/jadx/core/dex/trycatch/ExceptionHandler.java @@ -32,6 +32,8 @@ public class ExceptionHandler { private TryCatchBlock tryBlock; private boolean isFinally; + private boolean removed = false; + public ExceptionHandler(int addr, @Nullable ClassInfo type) { this.handleOffset = addr; addCatchType(type); @@ -138,6 +140,14 @@ public class ExceptionHandler { this.isFinally = isFinally; } + public boolean isRemoved() { + return removed; + } + + public void markForRemove() { + this.removed = true; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/jadx-core/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java b/jadx-core/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java index 65ed41b3b..e39b64e09 100644 --- a/jadx-core/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java +++ b/jadx-core/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java @@ -52,6 +52,17 @@ public class TryCatchBlock { return addedHandler; } + /** + * Use only before BlockSplitter + */ + public void removeSameHandlers(TryCatchBlock outerTry) { + for (ExceptionHandler handler : outerTry.getHandlers()) { + if (handlers.remove(handler)) { + handler.setTryBlock(outerTry); + } + } + } + public void removeHandler(MethodNode mth, ExceptionHandler handler) { for (Iterator it = handlers.iterator(); it.hasNext();) { ExceptionHandler h = it.next(); @@ -78,9 +89,14 @@ public class TryCatchBlock { } SplitterBlockAttr splitter = handler.getHandlerBlock().get(AType.SPLITTER_BLOCK); if (splitter != null) { - splitter.getBlock().remove(AType.SPLITTER_BLOCK); + BlockNode splitterBlock = splitter.getBlock(); + splitterBlock.remove(AType.SPLITTER_BLOCK); + for (BlockNode successor : splitterBlock.getSuccessors()) { + successor.remove(AType.SPLITTER_BLOCK); + } } } + handler.markForRemove(); } private void removeWholeBlock(MethodNode mth) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java index d6b312b45..df94b494d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java @@ -43,9 +43,12 @@ public class MarkFinallyVisitor extends AbstractVisitor { return; } try { + mth.clearExceptionHandlers(); + for (ExceptionHandler excHandler : mth.getExceptionHandlers()) { processExceptionHandler(mth, excHandler); } + mth.clearExceptionHandlers(); } catch (Exception e) { LOG.warn("Undo finally extract visitor, mth: {}", mth, e); try { diff --git a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java index 31e65e8a6..bec2aa1be 100644 --- a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java @@ -69,6 +69,16 @@ public class FileUtils { } } + public static boolean deleteDir(File dir) { + File[] content = dir.listFiles(); + if (content != null) { + for (File file : content) { + deleteDir(file); + } + } + return dir.delete(); + } + private static final Path TEMP_ROOT_DIR = createTempRootDir(); private static Path createTempRootDir() { diff --git a/jadx-core/src/test/java/jadx/tests/external/.gitignore b/jadx-core/src/test/java/jadx/tests/external/.gitignore index 810fe2873..8bdc5dc63 100644 --- a/jadx-core/src/test/java/jadx/tests/external/.gitignore +++ b/jadx-core/src/test/java/jadx/tests/external/.gitignore @@ -1 +1,2 @@ /ExternalTests.java +/*Tmp.java