core: fix processing of last instruction in 'try' block
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<PhiInsn> insnToRemove = new ArrayList<PhiInsn>();
|
||||
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<PhiInsn> insnToRemove) {
|
||||
@@ -194,9 +219,9 @@ public class SSATransform extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void removePhiList(MethodNode mth, List<PhiInsn> insnToRemove) {
|
||||
private static boolean removePhiList(MethodNode mth, List<PhiInsn> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ public class TestNestedLoops3 extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
setOutputCFG();
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
|
||||
@@ -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 {"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user