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 3c5071cc8..a1e5d9571 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 @@ -356,7 +356,8 @@ public class RegionMaker { if (loopExit == exit) { // try/catch at loop end BlockNode source = exitEdge.getSource(); - if (source.contains(AType.CATCH_BLOCK)) { + if (source.contains(AType.CATCH_BLOCK) + && source.getSuccessors().size() == 2) { BlockNode other = BlockUtils.selectOther(loopExit, source.getSuccessors()); if (other != null && other.contains(AType.EXC_HANDLER)) { insertBlock = source; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java index 60449e570..0d12c49a3 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java @@ -1,5 +1,6 @@ package jadx.core.dex.visitors.ssa; +import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.PhiListAttr; import jadx.core.dex.instructions.InsnType; @@ -40,7 +41,11 @@ public class SSATransform extends AbstractVisitor { placePhi(mth, i, la); } renameVariables(mth); - removeUselessPhi(mth); + fixLastTryCatchAssign(mth); + if (removeUselessPhi(mth)) { + renameVariables(mth); + } + } private static void placePhi(MethodNode mth, int regNum, LiveVarAnalysis la) { @@ -147,7 +152,27 @@ public class SSATransform extends AbstractVisitor { System.arraycopy(inputVars, 0, vars, 0, vars.length); } - private static void removeUselessPhi(MethodNode mth) { + private static void fixLastTryCatchAssign(MethodNode mth) { + for (BlockNode block : mth.getBasicBlocks()) { + PhiListAttr phiList = block.get(AType.PHI_LIST); + if (phiList == null || !block.contains(AType.EXC_HANDLER)) { + continue; + } + for (PhiInsn phi : phiList.getList()) { + for (int i = 0; i < phi.getArgsCount(); i++) { + RegisterArg arg = phi.getArg(i); + InsnNode parentInsn = arg.getAssignInsn(); + if (parentInsn != null + && parentInsn.getResult() != null + && parentInsn.contains(AFlag.TRY_LEAVE)) { + phi.removeArg(arg); + } + } + } + } + } + + private static boolean removeUselessPhi(MethodNode mth) { List insnToRemove = new ArrayList(); for (SSAVar var : mth.getSVars()) { // phi result not used @@ -167,7 +192,7 @@ public class SSATransform extends AbstractVisitor { removePhiWithSameArgs(phi, insnToRemove); } } - removePhiList(mth, insnToRemove); + return removePhiList(mth, insnToRemove); } private static void removePhiWithSameArgs(PhiInsn phi, List insnToRemove) { @@ -194,9 +219,9 @@ public class SSATransform extends AbstractVisitor { } } - private static void removePhiList(MethodNode mth, List insnToRemove) { + private static boolean removePhiList(MethodNode mth, List insnToRemove) { if (insnToRemove.isEmpty()) { - return; + return false; } for (BlockNode block : mth.getBasicBlocks()) { PhiListAttr phiList = block.get(AType.PHI_LIST); @@ -217,5 +242,6 @@ public class SSATransform extends AbstractVisitor { } } insnToRemove.clear(); + return true; } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/loops/TestNestedLoops3.java b/jadx-core/src/test/java/jadx/tests/integration/loops/TestNestedLoops3.java index 1d2e70c8c..4c2685032 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/loops/TestNestedLoops3.java +++ b/jadx-core/src/test/java/jadx/tests/integration/loops/TestNestedLoops3.java @@ -62,7 +62,6 @@ public class TestNestedLoops3 extends IntegrationTest { @Test public void test() { - setOutputCFG(); ClassNode cls = getClassNode(TestCls.class); String code = cls.getCode().toString(); diff --git a/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch6.java b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch6.java new file mode 100644 index 000000000..cb5950b61 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch6.java @@ -0,0 +1,53 @@ +package jadx.tests.integration.trycatch; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import java.io.IOException; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class TestTryCatch6 extends IntegrationTest { + + public static class TestCls { + private static boolean test(Object obj) { + boolean res = false; + while (true) { + try { + res = exc(obj); + return res; + } catch (IOException e) { + res = true; + } catch (Throwable e) { + if (obj == null) { + obj = new Object(); + } + } + } + } + + private static boolean exc(Object obj) throws IOException { + if (obj == null) { + throw new IOException(); + } + return true; + } + + public void check() { + assertTrue(test(new Object())); + } + } + + @Test + public void test() { + noDebugInfo(); + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("try {")); + } +}