Commit 24d22aaa authored by Skylot's avatar Skylot

core: fix 'if' detection

parent ebf78226
...@@ -72,20 +72,20 @@ public class BlockNode extends AttrNode implements IBlock { ...@@ -72,20 +72,20 @@ public class BlockNode extends AttrNode implements IBlock {
private static List<BlockNode> cleanSuccessors(BlockNode block) { private static List<BlockNode> cleanSuccessors(BlockNode block) {
List<BlockNode> sucList = block.getSuccessors(); List<BlockNode> sucList = block.getSuccessors();
List<BlockNode> nodes = new ArrayList<BlockNode>(sucList.size()); List<BlockNode> nodes = new ArrayList<BlockNode>(sucList.size());
LoopAttr loop = (LoopAttr) block.getAttributes().get(AttributeType.LOOP); if (block.getAttributes().contains(AttributeFlag.LOOP_END)) {
if (loop == null) { LoopAttr loop = (LoopAttr) block.getAttributes().get(AttributeType.LOOP);
for (BlockNode b : sucList) { for (BlockNode b : sucList) {
if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) { if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) {
// don't follow back edge
if (loop.getStart() == b) {
continue;
}
nodes.add(b); nodes.add(b);
} }
} }
} else { } else {
for (BlockNode b : sucList) { for (BlockNode b : sucList) {
if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) { if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) {
// don't follow back edge
if (loop.getStart() == b && loop.getEnd() == block) {
continue;
}
nodes.add(b); nodes.add(b);
} }
} }
......
...@@ -458,12 +458,14 @@ public class BlockMakerVisitor extends AbstractVisitor { ...@@ -458,12 +458,14 @@ public class BlockMakerVisitor extends AbstractVisitor {
if (exitBlock != otherExitBlock if (exitBlock != otherExitBlock
&& otherExitBlock.isDominator(pred) && otherExitBlock.isDominator(pred)
&& otherExitBlock.getPredecessors().size() == 1) { && otherExitBlock.getPredecessors().size() == 1) {
// merge
BlockNode otherPred = otherExitBlock.getPredecessors().get(0); BlockNode otherPred = otherExitBlock.getPredecessors().get(0);
removeConnection(otherPred, otherExitBlock); if (pred != otherPred) {
connect(otherPred, exitBlock); // merge
cleanExitNodes(mth); removeConnection(otherPred, otherExitBlock);
return true; connect(otherPred, exitBlock);
cleanExitNodes(mth);
return true;
}
} }
} }
} }
......
...@@ -201,8 +201,7 @@ public class RegionMaker { ...@@ -201,8 +201,7 @@ public class RegionMaker {
} }
List<BlockNode> merged = new ArrayList<BlockNode>(2); List<BlockNode> merged = new ArrayList<BlockNode>(2);
IfInfo mergedIf = mergeNestedIfNodes(condBlock, IfInfo mergedIf = mergeNestedIfNodes(condBlock, ifnode, merged);
ifnode.getThenBlock(), ifnode.getElseBlock(), merged);
if (mergedIf != null) { if (mergedIf != null) {
condBlock = mergedIf.getIfnode(); condBlock = mergedIf.getIfnode();
if (!loop.getLoopBlocks().contains(mergedIf.getThenBlock())) { if (!loop.getLoopBlocks().contains(mergedIf.getThenBlock())) {
...@@ -398,54 +397,56 @@ public class RegionMaker { ...@@ -398,54 +397,56 @@ public class RegionMaker {
} }
private BlockNode processIf(IRegion currentRegion, BlockNode block, IfNode ifnode, RegionStack stack) { private BlockNode processIf(IRegion currentRegion, BlockNode block, IfNode ifnode, RegionStack stack) {
BlockNode bThen = ifnode.getThenBlock();
BlockNode bElse = ifnode.getElseBlock();
if (block.getAttributes().contains(AttributeFlag.SKIP)) { if (block.getAttributes().contains(AttributeFlag.SKIP)) {
// block already included in other if region // block already included in other 'if' region
return bThen; return ifnode.getThenBlock();
} }
final BlockNode thenBlock;
final BlockNode elseBlock;
BlockNode out = null; BlockNode out = null;
BlockNode thenBlock = null;
BlockNode elseBlock = null;
IfRegion ifRegion = new IfRegion(currentRegion, block); IfRegion ifRegion = new IfRegion(currentRegion, block);
currentRegion.getSubBlocks().add(ifRegion); currentRegion.getSubBlocks().add(ifRegion);
IfInfo mergedIf = mergeNestedIfNodes(block, bThen, bElse, null); IfInfo mergedIf = mergeNestedIfNodes(block, ifnode, null);
if (mergedIf != null) { if (mergedIf != null) {
ifRegion.setCondition(mergedIf.getCondition()); ifRegion.setCondition(mergedIf.getCondition());
thenBlock = mergedIf.getThenBlock(); thenBlock = mergedIf.getThenBlock();
elseBlock = mergedIf.getElseBlock(); elseBlock = mergedIf.getElseBlock();
out = BlockUtils.getPathCrossBlockFor(mth, thenBlock, elseBlock); out = BlockUtils.getPathCrossBlockFor(mth, thenBlock, elseBlock);
} else { } else {
for (BlockNode d : block.getDominatesOn()) {
if (d != bThen && d != bElse) {
out = d;
break;
}
}
// invert condition (compiler often do it) // invert condition (compiler often do it)
ifnode.invertCondition(); ifnode.invertCondition();
bThen = ifnode.getThenBlock(); final BlockNode bThen = ifnode.getThenBlock();
bElse = ifnode.getElseBlock(); final BlockNode bElse = ifnode.getElseBlock();
thenBlock = bThen; // select 'then', 'else' and 'exit' blocks
// select else and exit blocks if (bElse.getPredecessors().size() != 1
if (block.getDominatesOn().size() == 2 && BlockUtils.isPathExists(bThen, bElse)) {
&& !BlockUtils.isPathExists(bThen, bElse)) { thenBlock = bThen;
elseBlock = null;
out = bElse;
} else if (bThen.getPredecessors().size() != 1
&& BlockUtils.isPathExists(bElse, bThen)) {
ifnode.invertCondition();
thenBlock = ifnode.getThenBlock();
elseBlock = null;
out = ifnode.getElseBlock();
} else if (block.getDominatesOn().size() == 2) {
thenBlock = bThen;
elseBlock = bElse; elseBlock = bElse;
out = BlockUtils.getPathCrossBlockFor(mth, bThen, bElse);
} else if (bElse.getPredecessors().size() != 1) {
thenBlock = bThen;
elseBlock = null;
out = bElse;
} else { } else {
if (bElse.getPredecessors().size() != 1) { thenBlock = bThen;
out = bElse; elseBlock = bElse;
} else { for (BlockNode d : block.getDominatesOn()) {
elseBlock = bElse; if (d != bThen && d != bElse) {
for (BlockNode d : block.getDominatesOn()) { out = d;
if (d != bThen && d != bElse) { break;
out = d;
break;
}
} }
} }
} }
...@@ -454,26 +455,26 @@ public class RegionMaker { ...@@ -454,26 +455,26 @@ public class RegionMaker {
} }
} }
if (elseBlock != null && stack.containsExit(elseBlock)) {
elseBlock = null;
}
stack.push(ifRegion); stack.push(ifRegion);
stack.addExit(out); stack.addExit(out);
ifRegion.setThenRegion(makeRegion(thenBlock, stack)); ifRegion.setThenRegion(makeRegion(thenBlock, stack));
ifRegion.setElseRegion(elseBlock == null ? null : makeRegion(elseBlock, stack)); if (elseBlock == null || stack.containsExit(elseBlock)) {
ifRegion.setElseRegion(null);
} else {
ifRegion.setElseRegion(makeRegion(elseBlock, stack));
}
stack.pop(); stack.pop();
return out; return out;
} }
private IfInfo mergeNestedIfNodes(BlockNode block, BlockNode bThen, BlockNode bElse, List<BlockNode> merged) { private IfInfo mergeNestedIfNodes(BlockNode block, IfNode ifnode, List<BlockNode> merged) {
IfInfo info = new IfInfo(); IfInfo info = new IfInfo();
info.setIfnode(block); info.setIfnode(block);
info.setCondition(IfCondition.fromIfBlock(block)); info.setCondition(IfCondition.fromIfBlock(block));
info.setThenBlock(bThen); info.setThenBlock(ifnode.getThenBlock());
info.setElseBlock(bElse); info.setElseBlock(ifnode.getElseBlock());
return mergeNestedIfNodes(info, merged); return mergeNestedIfNodes(info, merged);
} }
......
...@@ -3,8 +3,9 @@ package jadx.tests.internal.conditions; ...@@ -3,8 +3,9 @@ package jadx.tests.internal.conditions;
import jadx.api.InternalJadxTest; import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import static org.hamcrest.CoreMatchers.containsString; import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class TestTernary2 extends InternalJadxTest { public class TestTernary2 extends InternalJadxTest {
...@@ -20,12 +21,15 @@ public class TestTernary2 extends InternalJadxTest { ...@@ -20,12 +21,15 @@ public class TestTernary2 extends InternalJadxTest {
} }
} }
//@Test @Test
public void test() { public void test() {
ClassNode cls = getClassNode(TestCls.class); ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString(); String code = cls.getCode().toString();
System.out.println(code); System.out.println(code);
assertThat(code, containsString("assertTrue(f(1, 0) == 0);")); assertEquals(1, count(code, "assertTrue"));
assertEquals(1, count(code, "f(1, 0)"));
// TODO:
// assertThat(code, containsString("assertTrue(f(1, 0) == 0);"));
} }
} }
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