fix: improve condition branch checks in loops (#2274)
This commit is contained in:
@@ -120,8 +120,12 @@ public class IfMakerHelper {
|
||||
List<BlockNode> preds = block.getPredecessors();
|
||||
List<BlockNode> ifBlocks = info.getMergedBlocks();
|
||||
for (BlockNode pred : preds) {
|
||||
if (pred.contains(AFlag.LOOP_END)) {
|
||||
// ignore loop back edge
|
||||
continue;
|
||||
}
|
||||
BlockNode top = BlockUtils.skipSyntheticPredecessor(pred);
|
||||
if (!ifBlocks.contains(top) && !top.contains(AFlag.LOOP_END)) {
|
||||
if (!ifBlocks.contains(top)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class RegionMaker {
|
||||
Set<BlockNode> exitBlocksSet = loop.getExitNodes();
|
||||
|
||||
// set exit blocks scan order priority
|
||||
// this can help if loop have several exits (after using 'break' or 'return' in loop)
|
||||
// this can help if loop has several exits (after using 'break' or 'return' in loop)
|
||||
List<BlockNode> exitBlocks = new ArrayList<>(exitBlocksSet.size());
|
||||
BlockNode nextStart = getNextBlock(loopStart);
|
||||
if (nextStart != null && exitBlocksSet.remove(nextStart)) {
|
||||
@@ -299,10 +299,7 @@ public class RegionMaker {
|
||||
// skip nested loop condition
|
||||
continue;
|
||||
}
|
||||
BlockNode loopEnd = loop.getEnd();
|
||||
boolean exitAtLoopEnd = block == loopEnd
|
||||
|| (loopEnd.getInstructions().isEmpty() && ListUtils.isSingleElement(loopEnd.getPredecessors(), block));
|
||||
|
||||
boolean exitAtLoopEnd = isExitAtLoopEnd(block, loop);
|
||||
LoopRegion loopRegion = new LoopRegion(curRegion, loop, block, exitAtLoopEnd);
|
||||
boolean found;
|
||||
if (block == loop.getStart() || exitAtLoopEnd
|
||||
@@ -345,6 +342,18 @@ public class RegionMaker {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isExitAtLoopEnd(BlockNode exit, LoopInfo loop) {
|
||||
BlockNode loopEnd = loop.getEnd();
|
||||
if (exit == loopEnd) {
|
||||
return true;
|
||||
}
|
||||
BlockNode loopStart = loop.getStart();
|
||||
if (loopStart.getInstructions().isEmpty() && ListUtils.isSingleElement(loopStart.getSuccessors(), exit)) {
|
||||
return false;
|
||||
}
|
||||
return loopEnd.getInstructions().isEmpty() && ListUtils.isSingleElement(loopEnd.getPredecessors(), exit);
|
||||
}
|
||||
|
||||
private boolean checkLoopExits(LoopInfo loop, BlockNode mainExitBlock) {
|
||||
List<Edge> exitEdges = loop.getExitEdges();
|
||||
if (exitEdges.size() < 2) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package jadx.tests.integration.loops;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.RaungTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestLoopRestore2 extends RaungTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
disableCompilation(); // unreachable statement
|
||||
assertThat(getClassNodeFromRaung())
|
||||
.code()
|
||||
.containsOne("while (1 == 0) {");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
.version 45.3 # Java 1.1
|
||||
.class public super loops/TestLoopRestore2
|
||||
|
||||
.method public test([I[I)V
|
||||
.max stack 5
|
||||
.max locals 6
|
||||
|
||||
iconst_0
|
||||
istore 3
|
||||
sipush 0
|
||||
ifeq :L0
|
||||
goto :L1
|
||||
:L1
|
||||
sipush 1
|
||||
ifeq :L1
|
||||
goto :L0
|
||||
:L0
|
||||
iinc 3 1
|
||||
return
|
||||
.end method
|
||||
Reference in New Issue
Block a user