core: fix processing conditions in loop
This commit is contained in:
@@ -86,6 +86,11 @@ public class BlockNode extends AttrNode implements IBlock {
|
||||
for (BlockNode b : sucList) {
|
||||
if (b.contains(AType.EXC_HANDLER)) {
|
||||
toRemove.add(b);
|
||||
} else if (b.contains(AFlag.SYNTHETIC)) {
|
||||
List<BlockNode> s = b.getSuccessors();
|
||||
if (s.size() == 1 && s.get(0).contains(AType.EXC_HANDLER)) {
|
||||
toRemove.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (block.contains(AFlag.LOOP_END)) {
|
||||
|
||||
@@ -18,9 +18,13 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static jadx.core.utils.BlockUtils.isPathExists;
|
||||
|
||||
public class IfMakerHelper {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(IfMakerHelper.class);
|
||||
|
||||
private IfMakerHelper() {
|
||||
}
|
||||
@@ -59,10 +63,12 @@ public class IfMakerHelper {
|
||||
} else if (badElse) {
|
||||
info = new IfInfo(info.getCondition(), thenBlock, null);
|
||||
info.setOutBlock(null);
|
||||
LOG.debug("Stop processing blocks after bad 'else' in 'if': {}, method: {}", info, mth);
|
||||
} else {
|
||||
info = IfInfo.invert(info);
|
||||
info = new IfInfo(info.getCondition(), info.getThenBlock(), null);
|
||||
info.setOutBlock(null);
|
||||
LOG.debug("Stop processing blocks after bad 'then' in 'if': {}, method: {}", info, mth);
|
||||
}
|
||||
} else {
|
||||
List<BlockNode> thenSC = thenBlock.getCleanSuccessors();
|
||||
@@ -93,7 +99,12 @@ public class IfMakerHelper {
|
||||
private static boolean allPathsFromIf(BlockNode block, IfInfo info) {
|
||||
List<BlockNode> preds = block.getPredecessors();
|
||||
Set<BlockNode> ifBlocks = info.getMergedBlocks();
|
||||
return ifBlocks.containsAll(preds);
|
||||
for (BlockNode pred : preds) {
|
||||
if (!ifBlocks.contains(pred) && !pred.contains(AFlag.LOOP_END)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean sameElements(Collection<BlockNode> c1, Collection<BlockNode> c2) {
|
||||
|
||||
@@ -231,7 +231,8 @@ public class RegionMaker {
|
||||
}
|
||||
LoopRegion loopRegion = new LoopRegion(curRegion, block, block == loop.getEnd());
|
||||
boolean found;
|
||||
if (block == loop.getStart() || block == loop.getEnd()) {
|
||||
if (block == loop.getStart() || block == loop.getEnd()
|
||||
|| BlockUtils.isEmptySimplePath(loop.getStart(), block)) {
|
||||
found = true;
|
||||
} else if (block.getPredecessors().contains(loop.getStart())) {
|
||||
loopRegion.setPreCondition(loop.getStart());
|
||||
|
||||
@@ -301,4 +301,25 @@ public class BlockUtils {
|
||||
}
|
||||
return list.isEmpty() ? Collections.<BlockNode>emptyList() : list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if on path from start to end no instructions and no branches.
|
||||
*/
|
||||
public static boolean isEmptySimplePath(BlockNode start, BlockNode end) {
|
||||
if (start == end && start.getInstructions().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (!start.getInstructions().isEmpty() || start.getCleanSuccessors().size() != 1) {
|
||||
return false;
|
||||
}
|
||||
BlockNode block = getNextBlock(start);
|
||||
while (block != null
|
||||
&& block != end
|
||||
&& block.getCleanSuccessors().size() < 2
|
||||
&& block.getPredecessors().size() == 1
|
||||
&& block.getInstructions().isEmpty()) {
|
||||
block = getNextBlock(block);
|
||||
}
|
||||
return block == end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package jadx.tests.internal.others;
|
||||
|
||||
import jadx.api.InternalJadxTest;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static jadx.tests.utils.JadxMatchers.containsOne;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestLoopInTry extends InternalJadxTest {
|
||||
|
||||
public static class TestCls {
|
||||
private static boolean b = true;
|
||||
|
||||
public int test() {
|
||||
try {
|
||||
if (b) {
|
||||
throw new Exception();
|
||||
}
|
||||
while (f()) {
|
||||
s();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("exception");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void s() {
|
||||
}
|
||||
|
||||
private static boolean f() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
System.out.println(code);
|
||||
|
||||
assertThat(code, containsOne("try {"));
|
||||
assertThat(code, containsOne("if (b) {"));
|
||||
assertThat(code, containsOne("throw new Exception();"));
|
||||
assertThat(code, containsOne("while (f()) {"));
|
||||
assertThat(code, containsOne("s();"));
|
||||
assertThat(code, containsOne("} catch (Exception e) {"));
|
||||
assertThat(code, containsOne("return 1;"));
|
||||
assertThat(code, containsOne("return 0;"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user