Commit 5a24eac3 authored by Skylot's avatar Skylot

core: fix exit node search for synchronized block (fix #72)

parent a684118d
......@@ -504,18 +504,21 @@ public class RegionMaker {
return true;
}
private final Set<BlockNode> cacheSet = new HashSet<BlockNode>();
private BlockNode processMonitorEnter(IRegion curRegion, BlockNode block, InsnNode insn, RegionStack stack) {
SynchronizedRegion synchRegion = new SynchronizedRegion(curRegion, insn);
synchRegion.getSubBlocks().add(block);
curRegion.getSubBlocks().add(synchRegion);
Set<BlockNode> exits = new HashSet<BlockNode>();
cacheSet.clear();
Set<BlockNode> cacheSet = new HashSet<BlockNode>();
traverseMonitorExits(synchRegion, insn.getArg(0), block, exits, cacheSet);
for (InsnNode exitInsn : synchRegion.getExitInsns()) {
BlockNode insnBlock = BlockUtils.getBlockByInsn(mth, exitInsn);
if (insnBlock != null) {
insnBlock.add(AFlag.SKIP);
}
exitInsn.add(AFlag.SKIP);
InstructionRemover.unbindInsn(mth, exitInsn);
}
......@@ -524,16 +527,26 @@ public class RegionMaker {
ErrorsCounter.methodError(mth, "Unexpected end of synchronized block");
return null;
}
BlockNode exit;
BlockNode exit = null;
if (exits.size() == 1) {
exit = getNextBlock(exits.iterator().next());
} else {
} else if (exits.size() > 1) {
cacheSet.clear();
exit = traverseMonitorExitsCross(body, exits, cacheSet);
}
stack.push(synchRegion);
stack.addExit(exit);
if (exit != null) {
stack.addExit(exit);
} else {
for (BlockNode exitBlock : exits) {
// don't add exit blocks which leads to method end blocks ('return', 'throw', etc)
List<BlockNode> list = BlockUtils.buildSimplePath(exitBlock);
if (list.isEmpty() || !list.get(list.size() - 1).getSuccessors().isEmpty()) {
stack.addExit(exitBlock);
}
}
}
synchRegion.getSubBlocks().add(makeRegion(body, stack));
stack.pop();
return exit;
......
package jadx.tests.integration.synchronize;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsLines;
import static org.junit.Assert.assertThat;
public class TestSynchronized3 extends IntegrationTest {
public static class TestCls {
private int x;
public void f() {
}
public void test() {
while (true) {
synchronized (this) {
if (x == 0) {
throw new IllegalStateException("bad luck");
}
x++;
if (x == 10) {
break;
}
}
this.x++;
f();
}
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsLines(3, "}", "this.x++;", "f();"));
}
}
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