diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index 4a59d85aa..340595d2f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -504,18 +504,21 @@ public class RegionMaker { return true; } - private final Set cacheSet = new HashSet(); - 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 exits = new HashSet(); - cacheSet.clear(); + Set cacheSet = new HashSet(); 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 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; diff --git a/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized3.java b/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized3.java new file mode 100644 index 000000000..eb48b0f2e --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/synchronize/TestSynchronized3.java @@ -0,0 +1,43 @@ +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();")); + } +}