未验证 提交 f37c23db 编写于 作者: S Skylot

fix: use correct top block for try blocks with same start (#1304)

上级 d2bde0be
...@@ -323,23 +323,14 @@ public class BlockExceptionHandler { ...@@ -323,23 +323,14 @@ public class BlockExceptionHandler {
private static boolean wrapBlocksWithTryCatch(MethodNode mth, TryCatchBlockAttr tryCatchBlock) { private static boolean wrapBlocksWithTryCatch(MethodNode mth, TryCatchBlockAttr tryCatchBlock) {
List<BlockNode> blocks = tryCatchBlock.getBlocks(); List<BlockNode> blocks = tryCatchBlock.getBlocks();
BlockNode top = searchTopBlock(mth, blocks); BlockNode top = searchTopBlock(mth, blocks);
if (top.getPredecessors().isEmpty()) { if (top.getPredecessors().isEmpty() && top != mth.getEnterBlock()) {
return false; return false;
} }
BlockNode bottom = searchBottomBlock(mth, blocks); BlockNode bottom = searchBottomBlock(mth, blocks);
if (Consts.DEBUG_EXC_HANDLERS) { if (Consts.DEBUG_EXC_HANDLERS) {
LOG.debug("TryCatch #{} split: top {}, bottom: {}", tryCatchBlock.id(), top, bottom); LOG.debug("TryCatch #{} split: top {}, bottom: {}", tryCatchBlock.id(), top, bottom);
} }
BlockNode topSplitterBlock = getTopSplitterBlock(mth, top);
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);
}
topSplitterBlock.add(AFlag.EXC_TOP_SPLITTER); topSplitterBlock.add(AFlag.EXC_TOP_SPLITTER);
topSplitterBlock.add(AFlag.SYNTHETIC); topSplitterBlock.add(AFlag.SYNTHETIC);
...@@ -356,6 +347,10 @@ public class BlockExceptionHandler { ...@@ -356,6 +347,10 @@ public class BlockExceptionHandler {
BlockSplitter.connect(bottom, bottomSplitterBlock); BlockSplitter.connect(bottom, bottomSplitterBlock);
} }
if (Consts.DEBUG_EXC_HANDLERS) {
LOG.debug("TryCatch #{} result splitters: top {}, bottom: {}",
tryCatchBlock.id(), topSplitterBlock, bottomSplitterBlock);
}
connectSplittersAndHandlers(tryCatchBlock, topSplitterBlock, bottomSplitterBlock); connectSplittersAndHandlers(tryCatchBlock, topSplitterBlock, bottomSplitterBlock);
for (BlockNode block : blocks) { for (BlockNode block : blocks) {
...@@ -373,6 +368,25 @@ public class BlockExceptionHandler { ...@@ -373,6 +368,25 @@ public class BlockExceptionHandler {
return true; 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) { private static BlockNode searchTopBlock(MethodNode mth, List<BlockNode> blocks) {
BlockNode top = BlockUtils.getTopBlock(blocks); BlockNode top = BlockUtils.getTopBlock(blocks);
if (top != null) { if (top != null) {
......
...@@ -572,9 +572,9 @@ public class BlockUtils { ...@@ -572,9 +572,9 @@ public class BlockUtils {
return traverseSuccessorsUntil(start, end, new BitSet(), false); 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) { if (blocks.size() == 1) {
return blocks.iterator().next(); return blocks.get(0);
} }
for (BlockNode from : blocks) { for (BlockNode from : blocks) {
boolean top = true; boolean top = true;
...@@ -594,9 +594,9 @@ public class BlockUtils { ...@@ -594,9 +594,9 @@ public class BlockUtils {
/** /**
* Search last block in control flow graph from input set. * 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) { if (blocks.size() == 1) {
return blocks.iterator().next(); return blocks.get(0);
} }
for (BlockNode bottomCandidate : blocks) { for (BlockNode bottomCandidate : blocks) {
boolean bottom = true; boolean bottom = true;
......
...@@ -59,6 +59,10 @@ public class DebugUtils { ...@@ -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) { public static void dumpRaw(MethodNode mth, String desc) {
File out = new File("test-graph-" + desc + "-tmp"); File out = new File("test-graph-" + desc + "-tmp");
DotGraphVisitor.dumpRaw().save(out, mth); DotGraphVisitor.dumpRaw().save(out, mth);
......
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 {");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册