Commit c4109142 authored by Skylot's avatar Skylot

core: skip finally extract visitor on error

parent a046f1ca
...@@ -34,4 +34,7 @@ public class DepthTraversal { ...@@ -34,4 +34,7 @@ public class DepthTraversal {
e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e); e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e);
} }
} }
private DepthTraversal() {
}
} }
package jadx.core.dex.visitors.blocksmaker; package jadx.core.dex.visitors.blocksmaker;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.Jadx;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.IgnoreEdgeAttr; import jadx.core.dex.attributes.nodes.IgnoreEdgeAttr;
...@@ -14,26 +29,15 @@ import jadx.core.dex.trycatch.ExceptionHandler; ...@@ -14,26 +29,15 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.SplitterBlockAttr; import jadx.core.dex.trycatch.SplitterBlockAttr;
import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.dex.visitors.AbstractVisitor; import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair; import jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair;
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo; import jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo;
import jadx.core.dex.visitors.ssa.LiveVarAnalysis; import jadx.core.dex.visitors.ssa.LiveVarAnalysis;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.connect; import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.connect;
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.insertBlockBetween; import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.insertBlockBetween;
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.removeConnection; import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.removeConnection;
...@@ -46,7 +50,7 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -46,7 +50,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
if (mth.isNoCode() || mth.isNoExceptionHandlers()) { if (mth.isNoCode() || mth.isNoExceptionHandlers()) {
return; return;
} }
try {
boolean reloadBlocks = false; boolean reloadBlocks = false;
for (ExceptionHandler excHandler : mth.getExceptionHandlers()) { for (ExceptionHandler excHandler : mth.getExceptionHandlers()) {
if (processExceptionHandler(mth, excHandler)) { if (processExceptionHandler(mth, excHandler)) {
...@@ -57,6 +61,24 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -57,6 +61,24 @@ public class BlockFinallyExtract extends AbstractVisitor {
mergeReturnBlocks(mth); mergeReturnBlocks(mth);
BlockProcessor.rerun(mth); BlockProcessor.rerun(mth);
} }
} catch (Exception e) {
LOG.warn("Undo finally extract visitor, mth: {}", mth, e);
try {
// reload method without applying this visitor
// TODO: make more common and less hacky
mth.unload();
mth.load();
List<IDexTreeVisitor> passes = Jadx.getPassesList(mth.root().getArgs());
for (IDexTreeVisitor visitor : passes) {
if (visitor instanceof BlockFinallyExtract) {
break;
}
DepthTraversal.visit(visitor, mth);
}
} catch (Exception ee) {
LOG.error("Undo finally extract failed, mth: {}", mth, e);
}
}
} }
private static boolean processExceptionHandler(MethodNode mth, ExceptionHandler excHandler) { private static boolean processExceptionHandler(MethodNode mth, ExceptionHandler excHandler) {
...@@ -495,6 +517,12 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -495,6 +517,12 @@ public class BlockFinallyExtract extends AbstractVisitor {
LOG.warn("Finally extract failed: remBlock pred: {}, {}, method: {}", remBlock, remBlock.getPredecessors(), mth); LOG.warn("Finally extract failed: remBlock pred: {}, {}, method: {}", remBlock, remBlock.getPredecessors(), mth);
return false; return false;
} }
if (removeInfo.getOuts().isEmpty()) {
ErrorsCounter.methodError(mth, "Failed to extract finally block: empty outs");
return false;
}
// safe checks finished, altering blocks tree
// all error must throw exception to undo changes
BlockNode remBlockPred = remBlock.getPredecessors().get(0); BlockNode remBlockPred = remBlock.getPredecessors().get(0);
removeInfo.setStartPredecessor(remBlockPred); removeInfo.setStartPredecessor(remBlockPred);
...@@ -534,7 +562,11 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -534,7 +562,11 @@ public class BlockFinallyExtract extends AbstractVisitor {
} }
} }
BlocksPair out = removeInfo.getOuts().iterator().next(); Set<BlocksPair> outs = removeInfo.getOuts();
if (outs.isEmpty()) {
throw new JadxRuntimeException("Failed to extract finally block: all outs is deleted");
}
BlocksPair out = outs.iterator().next();
BlockNode rOut = out.getFirst(); BlockNode rOut = out.getFirst();
BlockNode sOut = out.getSecond(); BlockNode sOut = out.getSecond();
...@@ -556,8 +588,7 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -556,8 +588,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
BlockNode pred = filtPreds.get(0); BlockNode pred = filtPreds.get(0);
BlockNode repl = removeInfo.getBySecond(pred); BlockNode repl = removeInfo.getBySecond(pred);
if (repl == null) { if (repl == null) {
LOG.error("Block not found by {}, in {}, method: {}", pred, removeInfo, mth); throw new JadxRuntimeException("Block not found by " + pred + ", in " + removeInfo);
return false;
} }
removeConnection(pred, rOut); removeConnection(pred, rOut);
addIgnoredEdge(repl, rOut); addIgnoredEdge(repl, rOut);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment