core: prevent endless region processing (#340)

This commit is contained in:
Skylot
2018-08-23 20:56:32 +03:00
parent 0c041120f6
commit 7492889f4e
4 changed files with 34 additions and 15 deletions
@@ -1,5 +1,7 @@
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) {
int startBlockId = startBlock.getId();
Region region = regionByBlock[startBlockId];
if (region != null) {
return region;
Region r = new Region(stack.peekRegion());
if (startBlock == null) {
return r;
}
Region r = new Region(stack.peekRegion());
int startBlockId = startBlock.getId();
if (processedBlocks.get(startBlockId)) {
mth.addWarn("Removed duplicated region for block: " + startBlock + " " + startBlock.getAttributesString());
return r;
}
processedBlocks.set(startBlockId);
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) -> {