core: fix 'break' detection in loop
This commit is contained in:
@@ -181,7 +181,6 @@ public final class Decompiler {
|
||||
}
|
||||
|
||||
void processClass(ClassNode cls) {
|
||||
LOG.debug("processing class {} ...", cls);
|
||||
ProcessClass.process(cls, passes);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,8 @@ public class ClassNode extends LineAttrNode implements ILoadable {
|
||||
int sfIdx = cls.getSourceFileIndex();
|
||||
if (sfIdx != DexNode.NO_INDEX) {
|
||||
String fileName = dex.getString(sfIdx);
|
||||
if (!this.getFullName().contains(fileName.replace(".java", ""))) {
|
||||
if (!this.getFullName().contains(fileName.replace(".java", ""))
|
||||
&& !fileName.equals("SourceFile")) {
|
||||
this.getAttributes().add(new SourceFileAttr(fileName));
|
||||
LOG.debug("Class '{}' compiled from '{}'", this, fileName);
|
||||
}
|
||||
|
||||
@@ -238,13 +238,15 @@ public class RegionMaker {
|
||||
|
||||
exitBlocks.remove(condBlock);
|
||||
if (exitBlocks.size() > 0) {
|
||||
// add 'break' instruction before path cross between main loop exit and subexit
|
||||
BlockNode loopExit = BlockUtils.selectOther(loopBody, condBlock.getCleanSuccessors());
|
||||
for (Edge exitEdge : loop.getExitEdges()) {
|
||||
if (!exitBlocks.contains(exitEdge.getSource())) {
|
||||
continue;
|
||||
BlockNode loopExit = BlockUtils.selectOtherSafe(loopBody, condBlock.getCleanSuccessors());
|
||||
if (loopExit != null) {
|
||||
// add 'break' instruction before path cross between main loop exit and subexit
|
||||
for (Edge exitEdge : loop.getExitEdges()) {
|
||||
if (!exitBlocks.contains(exitEdge.getSource())) {
|
||||
continue;
|
||||
}
|
||||
insertBreak(stack, loopExit, exitEdge);
|
||||
}
|
||||
insertBreak(stack, loopExit, exitEdge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,18 @@ public class BlockUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockNode selectOtherSafe(BlockNode node, List<BlockNode> blocks) {
|
||||
int size = blocks.size();
|
||||
if (size == 1) {
|
||||
BlockNode first = blocks.get(0);
|
||||
return first != node ? first : null;
|
||||
} else if (size == 2) {
|
||||
BlockNode first = blocks.get(0);
|
||||
return first != node ? first : blocks.get(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<BlockNode> cleanBlockList(List<BlockNode> list) {
|
||||
List<BlockNode> ret = new ArrayList<BlockNode>(list.size());
|
||||
for (BlockNode block : list) {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package jadx.tests.internal.loops;
|
||||
|
||||
import jadx.api.InternalJadxTest;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestLoopDetection3 extends InternalJadxTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
private void test(TestCls parent, int pos) {
|
||||
Object item;
|
||||
while (--pos >= 0) {
|
||||
item = parent.get(pos);
|
||||
if (item instanceof String) {
|
||||
func((String) item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object get(int pos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void func(String item) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
System.out.println(code);
|
||||
|
||||
assertThat(code, containsString("while"));
|
||||
// TODO
|
||||
// assertThat(code, containsString("while (--pos >= 0) {"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user