core: fix loop handling
This commit is contained in:
@@ -21,6 +21,7 @@ import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.trycatch.CatchAttr;
|
||||
import jadx.core.dex.visitors.AbstractVisitor;
|
||||
import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.exceptions.JadxOverflowException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.connect;
|
||||
@@ -68,11 +69,16 @@ public class BlockProcessor extends AbstractVisitor {
|
||||
processNestedLoops(mth);
|
||||
}
|
||||
|
||||
private static boolean removeEmptyBlock(MethodNode mth, BlockNode block) {
|
||||
if (block.getInstructions().isEmpty()
|
||||
private static boolean canRemoveBlock(BlockNode block) {
|
||||
return block.getInstructions().isEmpty()
|
||||
&& !block.isSynthetic()
|
||||
&& block.isAttrStorageEmpty()
|
||||
&& block.getSuccessors().size() <= 1) {
|
||||
&& block.getSuccessors().size() <= 1
|
||||
&& !block.getPredecessors().isEmpty();
|
||||
}
|
||||
|
||||
private static boolean removeEmptyBlock(BlockNode block) {
|
||||
if (canRemoveBlock(block)) {
|
||||
LOG.debug("Removing empty block: {}", block);
|
||||
if (block.getSuccessors().size() == 1) {
|
||||
BlockNode successor = block.getSuccessors().get(0);
|
||||
@@ -245,7 +251,13 @@ public class BlockProcessor extends AbstractVisitor {
|
||||
exit.setDomFrontier(EMPTY);
|
||||
}
|
||||
for (BlockNode block : mth.getBasicBlocks()) {
|
||||
computeBlockDF(mth, block);
|
||||
try {
|
||||
computeBlockDF(mth, block);
|
||||
} catch (StackOverflowError e) {
|
||||
throw new JadxOverflowException("Failed compute block dominance frontier");
|
||||
} catch (Exception e) {
|
||||
throw new JadxRuntimeException("Failed compute block dominance frontier", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +265,7 @@ public class BlockProcessor extends AbstractVisitor {
|
||||
if (block.getDomFrontier() != null) {
|
||||
return;
|
||||
}
|
||||
block.getDominatesOn().forEach(c -> computeBlockDF(mth, c));
|
||||
block.getDominatesOn().forEach(domBlock -> computeBlockDF(mth, domBlock));
|
||||
List<BlockNode> blocks = mth.getBasicBlocks();
|
||||
BitSet domFrontier = null;
|
||||
for (BlockNode s : block.getSuccessors()) {
|
||||
@@ -367,7 +379,7 @@ public class BlockProcessor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
for (BlockNode basicBlock : basicBlocks) {
|
||||
if (removeEmptyBlock(mth, basicBlock)) {
|
||||
if (removeEmptyBlock(basicBlock)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package jadx.tests.integration.loops;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static jadx.tests.api.utils.JadxMatchers.countString;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestLoopCondition5 extends SmaliTest {
|
||||
|
||||
public static class TestCls {
|
||||
private static int lastIndexOf(int[] array, int target, int start, int end) {
|
||||
for (int i = end - 1; i >= start; i--) {
|
||||
if (array[i] == target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test0() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("for ("));
|
||||
assertThat(code, containsOne("return -1;"));
|
||||
assertThat(code, countString(2, "return "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
ClassNode cls = getClassNodeFromSmaliWithPath("loops", "TestLoopCondition5");
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, anyOf(containsOne("for ("), containsOne("while (true) {")));
|
||||
assertThat(code, containsOne("return -1;"));
|
||||
assertThat(code, countString(2, "return "));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
.class public LTestLoopCondition5;
|
||||
.super Ljava/lang/Object;
|
||||
.source "TestLoopCondition5.java"
|
||||
|
||||
.method private static lastIndexOf([IIII)I
|
||||
.locals 1
|
||||
|
||||
add-int/lit8 p3, p3, -0x1
|
||||
|
||||
:goto_0
|
||||
const/4 v0, -0x1
|
||||
|
||||
if-lt p3, p2, :cond_1
|
||||
|
||||
.line 219
|
||||
aget v0, p0, p3
|
||||
|
||||
if-ne v0, p1, :cond_0
|
||||
|
||||
return p3
|
||||
|
||||
:cond_0
|
||||
add-int/lit8 p3, p3, -0x1
|
||||
|
||||
goto :goto_0
|
||||
|
||||
:cond_1
|
||||
move p3, v0
|
||||
|
||||
return p3
|
||||
.end method
|
||||
Reference in New Issue
Block a user