Commit 7492889f authored by Skylot's avatar Skylot

core: prevent endless region processing (#340)

parent 0c041120
package jadx.core.dex.instructions;
import java.util.List;
import com.android.dx.io.instructions.DecodedInstruction;
import jadx.core.dex.instructions.args.ArgType;
......@@ -57,11 +59,12 @@ public class IfNode extends GotoNode {
@Override
public void initBlocks(BlockNode curBlock) {
thenBlock = getBlockByOffset(target, curBlock.getSuccessors());
if (curBlock.getSuccessors().size() == 1) {
List<BlockNode> successors = curBlock.getSuccessors();
thenBlock = getBlockByOffset(target, successors);
if (successors.size() == 1) {
elseBlock = thenBlock;
} else {
elseBlock = selectOther(thenBlock, curBlock.getSuccessors());
elseBlock = selectOther(thenBlock, successors);
}
}
......
......@@ -2,6 +2,7 @@ package jadx.core.dex.visitors.regions;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.slf4j.Logger;
......@@ -52,6 +53,12 @@ public class IfMakerHelper {
BlockNode thenBlock = info.getThenBlock();
BlockNode elseBlock = info.getElseBlock();
if (Objects.equals(thenBlock, elseBlock)) {
IfInfo ifInfo = new IfInfo(info, null, null);
ifInfo.setOutBlock(thenBlock);
return ifInfo;
}
// select 'then', 'else' and 'exit' blocks
if (thenBlock.contains(AFlag.RETURN) && elseBlock.contains(AFlag.RETURN)) {
info.setOutBlock(null);
......
......@@ -60,21 +60,26 @@ public class RegionMaker {
private final MethodNode mth;
private int regionsCount;
private Region[] regionByBlock;
private BitSet processedBlocks;
public RegionMaker(MethodNode mth) {
this.mth = mth;
this.regionByBlock = new Region[mth.getBasicBlocks().size()];
this.processedBlocks = new BitSet(mth.getBasicBlocks().size());
}
public Region makeRegion(BlockNode startBlock, RegionStack stack) {
Region r = new Region(stack.peekRegion());
if (startBlock == null) {
return r;
}
int startBlockId = startBlock.getId();
Region region = regionByBlock[startBlockId];
if (region != null) {
return region;
if (processedBlocks.get(startBlockId)) {
mth.addWarn("Removed duplicated region for block: " + startBlock + " " + startBlock.getAttributesString());
return r;
}
processedBlocks.set(startBlockId);
Region r = new Region(stack.peekRegion());
BlockNode next = startBlock;
while (next != null) {
next = traverse(r, next, stack);
......@@ -83,7 +88,6 @@ public class RegionMaker {
throw new JadxRuntimeException("Regions count limit reached");
}
}
regionByBlock[startBlockId] = r;
return r;
}
......@@ -201,6 +205,7 @@ public class RegionMaker {
loopStart.remove(AType.LOOP);
loop.getEnd().add(AFlag.SKIP);
stack.addExit(loop.getEnd());
processedBlocks.clear(loopStart.getId());
Region body = makeRegion(loopStart, stack);
loopRegion.setBody(body);
loopStart.addAttr(AType.LOOP, loop);
......@@ -296,6 +301,7 @@ public class RegionMaker {
curRegion.getSubBlocks().add(loopRegion);
loopStart.remove(AType.LOOP);
processedBlocks.clear(loopStart.getId());
stack.push(loopRegion);
BlockNode out = null;
......@@ -850,7 +856,7 @@ public class RegionMaker {
}
private Map<BlockNode, List<Object>> reOrderSwitchCases(Map<BlockNode, List<Object>> blocksMap,
Map<BlockNode, BlockNode> fallThroughCases) {
Map<BlockNode, BlockNode> fallThroughCases) {
List<BlockNode> list = new ArrayList<>(blocksMap.size());
list.addAll(blocksMap.keySet());
list.sort((a, b) -> {
......
......@@ -5,6 +5,7 @@ import org.junit.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsLines;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
......@@ -18,10 +19,8 @@ public class TestWrongCode extends IntegrationTest {
return a.length;
}
@SuppressWarnings("empty")
private int test2(int a) {
if (a == 0) {
;
}
return a;
}
......@@ -36,7 +35,11 @@ public class TestWrongCode extends IntegrationTest {
assertThat(code, containsOne("int[] a = null;"));
assertThat(code, containsOne("return a.length;"));
assertThat(code, containsString("return a == 0 ? a : a;"));
assertThat(code, containsLines(2,
"if (a == 0) {",
"}",
"return a;"
));
}
@Test
......
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