core: prevent endless region processing (#340)
This commit is contained in:
@@ -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) -> {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user