Commit f366eac7 authored by Skylot's avatar Skylot

core: fix switch in loop (fix #52)

parent 46d3992b
......@@ -663,7 +663,8 @@ public class RegionMaker {
Map<BlockNode, BlockNode> fallThroughCases = new LinkedHashMap<BlockNode, BlockNode>();
BitSet outs = new BitSet(mth.getBasicBlocks().size());
List<BlockNode> basicBlocks = mth.getBasicBlocks();
BitSet outs = new BitSet(basicBlocks.size());
outs.or(block.getDomFrontier());
for (BlockNode s : block.getCleanSuccessors()) {
BitSet df = s.getDomFrontier();
......@@ -672,8 +673,8 @@ public class RegionMaker {
if (df.cardinality() > 2) {
LOG.debug("Unexpected case pattern, block: {}, mth: {}", s, mth);
} else {
BlockNode first = mth.getBasicBlocks().get(df.nextSetBit(0));
BlockNode second = mth.getBasicBlocks().get(df.nextSetBit(first.getId() + 1));
BlockNode first = basicBlocks.get(df.nextSetBit(0));
BlockNode second = basicBlocks.get(df.nextSetBit(first.getId() + 1));
if (second.getDomFrontier().get(first.getId())) {
fallThroughCases.put(s, second);
df = new BitSet(df.size());
......@@ -687,6 +688,11 @@ public class RegionMaker {
}
outs.or(df);
}
outs.clear(block.getId());
if (loop != null) {
outs.clear(loop.getStart().getId());
}
stack.push(sw);
stack.addExits(BlockUtils.bitSetToBlocks(mth, outs));
......@@ -709,9 +715,8 @@ public class RegionMaker {
}
if (outs.cardinality() > 1) {
// filter loop start and successors of other blocks
List<BlockNode> blocks = mth.getBasicBlocks();
for (int i = outs.nextSetBit(0); i >= 0; i = outs.nextSetBit(i + 1)) {
BlockNode b = blocks.get(i);
BlockNode b = basicBlocks.get(i);
outs.andNot(b.getDomFrontier());
if (b.contains(AFlag.LOOP_START)) {
outs.clear(b.getId());
......@@ -745,7 +750,7 @@ public class RegionMaker {
}
BlockNode out = null;
if (outs.cardinality() == 1) {
out = mth.getBasicBlocks().get(outs.nextSetBit(0));
out = basicBlocks.get(outs.nextSetBit(0));
stack.addExit(out);
} else if (loop == null && outs.cardinality() > 1) {
LOG.warn("Can't detect out node for switch block: {} in {}", block, mth);
......
package jadx.tests.integration.switches;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class TestSwitchInLoop extends IntegrationTest {
public static class TestCls {
public int test(int k) {
int a = 0;
while (true) {
switch (k) {
case 0:
return a;
default:
a++;
k >>= 1;
}
}
}
public void check() {
assertEquals(1, test(1));
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("switch (k) {"));
assertThat(code, containsOne("case 0:"));
assertThat(code, containsOne("return a;"));
assertThat(code, containsOne("default:"));
assertThat(code, containsOne("a++;"));
assertThat(code, containsOne("k >>= 1;"));
}
}
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