fix: use correct top block for try blocks with same start (#1304)
This commit is contained in:
@@ -323,23 +323,14 @@ public class BlockExceptionHandler {
|
||||
private static boolean wrapBlocksWithTryCatch(MethodNode mth, TryCatchBlockAttr tryCatchBlock) {
|
||||
List<BlockNode> blocks = tryCatchBlock.getBlocks();
|
||||
BlockNode top = searchTopBlock(mth, blocks);
|
||||
if (top.getPredecessors().isEmpty()) {
|
||||
if (top.getPredecessors().isEmpty() && top != mth.getEnterBlock()) {
|
||||
return false;
|
||||
}
|
||||
BlockNode bottom = searchBottomBlock(mth, blocks);
|
||||
|
||||
if (Consts.DEBUG_EXC_HANDLERS) {
|
||||
LOG.debug("TryCatch #{} split: top {}, bottom: {}", tryCatchBlock.id(), top, bottom);
|
||||
}
|
||||
|
||||
BlockNode topSplitterBlock;
|
||||
if (top == mth.getEnterBlock()) {
|
||||
BlockNode fixedTop = mth.getEnterBlock().getSuccessors().get(0);
|
||||
topSplitterBlock = BlockSplitter.blockSplitTop(mth, fixedTop);
|
||||
} else {
|
||||
BlockNode existTopSplitter = BlockUtils.getBlockWithFlag(top.getPredecessors(), AFlag.EXC_TOP_SPLITTER);
|
||||
topSplitterBlock = existTopSplitter != null ? existTopSplitter : BlockSplitter.blockSplitTop(mth, top);
|
||||
}
|
||||
BlockNode topSplitterBlock = getTopSplitterBlock(mth, top);
|
||||
topSplitterBlock.add(AFlag.EXC_TOP_SPLITTER);
|
||||
topSplitterBlock.add(AFlag.SYNTHETIC);
|
||||
|
||||
@@ -356,6 +347,10 @@ public class BlockExceptionHandler {
|
||||
BlockSplitter.connect(bottom, bottomSplitterBlock);
|
||||
}
|
||||
|
||||
if (Consts.DEBUG_EXC_HANDLERS) {
|
||||
LOG.debug("TryCatch #{} result splitters: top {}, bottom: {}",
|
||||
tryCatchBlock.id(), topSplitterBlock, bottomSplitterBlock);
|
||||
}
|
||||
connectSplittersAndHandlers(tryCatchBlock, topSplitterBlock, bottomSplitterBlock);
|
||||
|
||||
for (BlockNode block : blocks) {
|
||||
@@ -373,6 +368,25 @@ public class BlockExceptionHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BlockNode getTopSplitterBlock(MethodNode mth, BlockNode top) {
|
||||
if (top == mth.getEnterBlock()) {
|
||||
BlockNode fixedTop = mth.getEnterBlock().getSuccessors().get(0);
|
||||
return BlockSplitter.blockSplitTop(mth, fixedTop);
|
||||
}
|
||||
BlockNode existPredTopSplitter = BlockUtils.getBlockWithFlag(top.getPredecessors(), AFlag.EXC_TOP_SPLITTER);
|
||||
if (existPredTopSplitter != null) {
|
||||
return existPredTopSplitter;
|
||||
}
|
||||
// try to reuse exists splitter on empty simple path below top block
|
||||
if (top.getCleanSuccessors().size() == 1 && top.getInstructions().isEmpty()) {
|
||||
BlockNode otherTopSplitter = BlockUtils.getBlockWithFlag(top.getCleanSuccessors(), AFlag.EXC_TOP_SPLITTER);
|
||||
if (otherTopSplitter != null && otherTopSplitter.getPredecessors().size() == 1) {
|
||||
return otherTopSplitter;
|
||||
}
|
||||
}
|
||||
return BlockSplitter.blockSplitTop(mth, top);
|
||||
}
|
||||
|
||||
private static BlockNode searchTopBlock(MethodNode mth, List<BlockNode> blocks) {
|
||||
BlockNode top = BlockUtils.getTopBlock(blocks);
|
||||
if (top != null) {
|
||||
|
||||
@@ -572,9 +572,9 @@ public class BlockUtils {
|
||||
return traverseSuccessorsUntil(start, end, new BitSet(), false);
|
||||
}
|
||||
|
||||
public static BlockNode getTopBlock(Collection<BlockNode> blocks) {
|
||||
public static BlockNode getTopBlock(List<BlockNode> blocks) {
|
||||
if (blocks.size() == 1) {
|
||||
return blocks.iterator().next();
|
||||
return blocks.get(0);
|
||||
}
|
||||
for (BlockNode from : blocks) {
|
||||
boolean top = true;
|
||||
@@ -594,9 +594,9 @@ public class BlockUtils {
|
||||
/**
|
||||
* Search last block in control flow graph from input set.
|
||||
*/
|
||||
public static BlockNode getBottomBlock(Collection<BlockNode> blocks) {
|
||||
public static BlockNode getBottomBlock(List<BlockNode> blocks) {
|
||||
if (blocks.size() == 1) {
|
||||
return blocks.iterator().next();
|
||||
return blocks.get(0);
|
||||
}
|
||||
for (BlockNode bottomCandidate : blocks) {
|
||||
boolean bottom = true;
|
||||
|
||||
@@ -59,6 +59,10 @@ public class DebugUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void dumpRawTest(MethodNode mth, String desc) {
|
||||
dumpRaw(mth, desc, method -> method.getName().equals("test"));
|
||||
}
|
||||
|
||||
public static void dumpRaw(MethodNode mth, String desc) {
|
||||
File out = new File("test-graph-" + desc + "-tmp");
|
||||
DotGraphVisitor.dumpRaw().save(out, mth);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package jadx.tests.integration.trycatch;
|
||||
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
import jadx.tests.api.extensions.inputs.InputPlugin;
|
||||
import jadx.tests.api.extensions.inputs.TestWithInputPlugins;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestTryCatchFinally13 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
public void test(int i) {
|
||||
try {
|
||||
doSomething1();
|
||||
if (i == -12) {
|
||||
return;
|
||||
}
|
||||
if (i > 10) {
|
||||
doSomething2();
|
||||
} else if (i == -1) {
|
||||
doSomething3();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logError();
|
||||
} finally {
|
||||
doSomething4();
|
||||
}
|
||||
}
|
||||
|
||||
private void logError() {
|
||||
}
|
||||
|
||||
private void doSomething1() {
|
||||
}
|
||||
|
||||
private void doSomething2() {
|
||||
}
|
||||
|
||||
private void doSomething3() {
|
||||
}
|
||||
|
||||
private void doSomething4() {
|
||||
}
|
||||
}
|
||||
|
||||
@TestWithInputPlugins({ InputPlugin.DEX, InputPlugin.JAVA })
|
||||
public void test() {
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code()
|
||||
.containsOne("} finally {");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user