Skip to content

Commit

Permalink
chore: show try/catch processing problems in code comments
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Dec 25, 2018
1 parent e9591ef commit eadf046
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public AType<SplitterBlockAttr> getType() {

@Override
public String toString() {
return "Splitter: " + block;
return "Splitter:" + block;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void visit(MethodNode mth) {

for (BlockNode block : mth.getBasicBlocks()) {
block.updateCleanSuccessors();
fixSplitterBlock(block);
fixSplitterBlock(mth, block);
}

mth.finishBasicBlocks();
Expand All @@ -36,7 +36,7 @@ public void visit(MethodNode mth) {
* For evey exception handler must be only one splitter block,
* select correct one and remove others if necessary.
*/
private static void fixSplitterBlock(BlockNode block) {
private static void fixSplitterBlock(MethodNode mth, BlockNode block) {
ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) {
return;
Expand All @@ -58,7 +58,7 @@ private static void fixSplitterBlock(BlockNode block) {
}
BlockNode topSplitter = BlockUtils.getTopBlock(splitters.keySet());
if (topSplitter == null) {
LOG.warn("Unknown top splitter block from list: {}", splitters);
mth.addWarn("Unknown top exception splitter block from list: " + splitters);
return;
}
for (Map.Entry<BlockNode, SplitterBlockAttr> entry : splitters.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void processBlock(MethodNode mth, IBlock container) {
&& !block.getInstructions().isEmpty()
&& !block.contains(AFlag.SKIP)) {
String blockCode = getBlockInsnStr(mth, block);
mth.addWarn("Missing block: " + block + ", code:" + CodeWriter.NL + blockCode);
mth.addWarn("Missing block: " + block + ", code skipped:" + CodeWriter.NL + blockCode);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;

/**
* Extract blocks to separate try/catch region
Expand Down Expand Up @@ -67,34 +66,39 @@ private static void searchTryCatchDominators(MethodNode mth, Map<BlockNode, TryC
// for each try block search nearest dominator block
for (TryCatchBlock tb : tryBlocks) {
if (tb.getHandlersCount() == 0) {
LOG.warn("No exception handlers in catch block, method: {}", mth);
mth.addWarn("No exception handlers in catch block: " + tb);
continue;
}
BitSet bs = new BitSet(mth.getBasicBlocks().size());
for (ExceptionHandler excHandler : tb.getHandlers()) {
BlockNode handlerBlock = excHandler.getHandlerBlock();
if (handlerBlock != null) {
SplitterBlockAttr splitter = handlerBlock.get(AType.SPLITTER_BLOCK);
if (splitter != null) {
BlockNode block = splitter.getBlock();
bs.set(block.getId());
}
}
}
List<BlockNode> domBlocks = BlockUtils.bitSetToBlocks(mth, bs);
BlockNode domBlock;
if (domBlocks.size() != 1) {
domBlock = BlockUtils.getTopBlock(domBlocks);
if (domBlock == null) {
throw new JadxRuntimeException("Exception block dominator not found, method:" + mth + ", dom blocks: " + domBlocks);
processTryCatchBlock(mth, tb, tryBlocksMap);
}
}

private static void processTryCatchBlock(MethodNode mth, TryCatchBlock tb, Map<BlockNode, TryCatchBlock> tryBlocksMap) {
BitSet bs = new BitSet(mth.getBasicBlocks().size());
for (ExceptionHandler excHandler : tb.getHandlers()) {
BlockNode handlerBlock = excHandler.getHandlerBlock();
if (handlerBlock != null) {
SplitterBlockAttr splitter = handlerBlock.get(AType.SPLITTER_BLOCK);
if (splitter != null) {
BlockNode block = splitter.getBlock();
bs.set(block.getId());
}
} else {
domBlock = domBlocks.get(0);
}
TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
if (prevTB != null) {
ErrorsCounter.methodWarn(mth, "Failed to process nested try/catch");
}
List<BlockNode> domBlocks = BlockUtils.bitSetToBlocks(mth, bs);
BlockNode domBlock;
if (domBlocks.size() != 1) {
domBlock = BlockUtils.getTopBlock(domBlocks);
if (domBlock == null) {
mth.addWarn("Exception block dominator not found, dom blocks: " + domBlocks);
return;
}
} else {
domBlock = domBlocks.get(0);
}
TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
if (prevTB != null) {
mth.addWarn("Failed to process nested try/catch");
}
}

Expand All @@ -105,7 +109,7 @@ private static boolean checkAndWrap(MethodNode mth, Map<BlockNode, TryCatchBlock
if (region.getSubBlocks().contains(dominator)) {
TryCatchBlock tb = tryBlocksMap.get(dominator);
if (!wrapBlocks(region, tb, dominator)) {
ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for " + region);
ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for region: " + region);
}
tryBlocksMap.remove(dominator);
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ public IRegion processTryCatchBlocks(MethodNode mth) {
}
}
for (ExceptionHandler handler : tc.getHandlers()) {
processExcHandler(handler, exits);
processExcHandler(mth, handler, exits);
}
}
return processHandlersOutBlocks(mth, tcs);
Expand Down Expand Up @@ -968,12 +968,12 @@ protected IRegion processHandlersOutBlocks(MethodNode mth, Set<TryCatchBlock> tc
return excOutRegion;
}

private void processExcHandler(ExceptionHandler handler, Set<BlockNode> exits) {
private void processExcHandler(MethodNode mth, ExceptionHandler handler, Set<BlockNode> exits) {
BlockNode start = handler.getHandlerBlock();
if (start == null) {
return;
}
RegionStack stack = new RegionStack(mth);
RegionStack stack = new RegionStack(this.mth);
BlockNode dom;
if (handler.isFinally()) {
SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK);
Expand All @@ -986,19 +986,19 @@ private void processExcHandler(ExceptionHandler handler, Set<BlockNode> exits) {
stack.addExits(exits);
}
BitSet domFrontier = dom.getDomFrontier();
List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(mth, domFrontier);
boolean inLoop = mth.getLoopForBlock(start) != null;
List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(this.mth, domFrontier);
boolean inLoop = this.mth.getLoopForBlock(start) != null;
for (BlockNode exit : handlerExits) {
if ((!inLoop || BlockUtils.isPathExists(start, exit))
&& RegionUtils.isRegionContainsBlock(mth.getRegion(), exit)) {
&& RegionUtils.isRegionContainsBlock(this.mth.getRegion(), exit)) {
stack.addExit(exit);
}
}
handler.setHandlerRegion(makeRegion(start, stack));

ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) {
LOG.warn("Missing exception handler attribute for start block");
mth.addWarn("Missing exception handler attribute for start block: " + start);
} else {
handler.getHandlerRegion().addAttr(excHandlerAttr);
}
Expand Down
27 changes: 20 additions & 7 deletions jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,36 @@ private void printMethods(ClassNode classNode, @NotNull Pattern mthPattern) {
String[] lines = code.split(CodeWriter.NL);
for (MethodNode mth : classNode.getMethods()) {
if (mthPattern.matcher(mth.getName()).matches()) {
int decompiledLine = mth.getDecompiledLine();
int decompiledLine = mth.getDecompiledLine() - 1;
StringBuilder mthCode = new StringBuilder();
int startLine = getCommentLinesCount(lines, decompiledLine);
int brackets = 0;
for (int i = decompiledLine - 1; i > 0 && i < lines.length; i++) {
for (int i = startLine; i > 0 && i < lines.length; i++) {
String line = lines[i];
mthCode.append(line).append(CodeWriter.NL);
brackets += StringUtils.countMatches(line, '{');
brackets -= StringUtils.countMatches(line, '}');
if (brackets <= 0) {
break;
if (i >= decompiledLine) {
brackets += StringUtils.countMatches(line, '{');
brackets -= StringUtils.countMatches(line, '}');
if (brackets <= 0) {
break;
}
}
}
LOG.info("\n{}", mthCode);
LOG.info("Print method: {}\n{}", mth.getMethodInfo().getShortId(), mthCode);
}
}
}

protected int getCommentLinesCount(String[] lines, int line) {
for (int i = line - 1; i > 0 && i < lines.length; i--) {
String str = lines[i];
if (str.isEmpty() || str.equals(CodeWriter.NL)) {
return i + 1;
}
}
return 0;
}

private void printErrorReport(JadxDecompiler jadx) {
jadx.printErrorsReport();
assertThat(jadx.getErrorsCount(), is(0));
Expand Down

0 comments on commit eadf046

Please sign in to comment.