Commit 52deb48a authored by Skylot's avatar Skylot

fix: move instruction out of try/catch (#468)

parent 214866fc
......@@ -316,4 +316,24 @@ public class InsnNode extends LineAttrNode {
}
return INSN_CLONER.deepClone(this);
}
public boolean canThrowException() {
switch (getType()) {
case RETURN:
case IF:
case GOTO:
case MOVE:
case MOVE_EXCEPTION:
case NEG:
case CONST:
case CONST_STR:
case CONST_CLASS:
case CMP_L:
case CMP_G:
return false;
default:
return true;
}
}
}
......@@ -321,16 +321,24 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
int offset = aTry.getStartAddress();
int end = offset + aTry.getInstructionCount() - 1;
InsnNode insn = insnByOffset[offset];
insn.add(AFlag.TRY_ENTER);
boolean tryBlockStarted = false;
InsnNode insn = null;
while (offset <= end && offset >= 0) {
insn = insnByOffset[offset];
catchBlock.addInsn(insn);
if (insn != null) {
if (tryBlockStarted) {
catchBlock.addInsn(insn);
} else if (insn.canThrowException()) {
insn.add(AFlag.TRY_ENTER);
catchBlock.addInsn(insn);
tryBlockStarted = true;
}
}
offset = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
}
if (insnByOffset[end] != null) {
insnByOffset[end].add(AFlag.TRY_LEAVE);
} else {
} else if (insn != null) {
insn.add(AFlag.TRY_LEAVE);
}
}
......
package jadx.tests.integration.trycatch;
import org.junit.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestTryCatchStartOnMove extends SmaliTest {
// private static void test(String s) {
// try {
// call(s);
// } catch (Exception unused) {
// System.out.println("Failed call for " + s);
// }
// }
//
// private static void call(String s) {
// }
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPkg("trycatch", "TestTryCatchStartOnMove");
String code = cls.getCode().toString();
assertThat(code, containsOne("try {"));
assertThat(code, containsOne("} catch (Exception e) {"));
assertThat(code, containsOne("System.out.println(\"Failed call for \" + str"));
}
}
.class public Ltrycatch/TestTryCatchStartOnMove;
.super Ljava/lang/Object;
# direct methods
.method private static test(Ljava/lang/String;)V
.registers 5
:try_start
move v3, p0
invoke-static {v3}, Ltrycatch/TestTryCatchStartOnMove;->call(Ljava/lang/String;)V
:try_end
.catch Ljava/lang/Exception; {:try_start .. :try_end} :catch
:goto_ret
return-void
:catch
move-exception v0
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, "Failed call for "
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_ret
.end method
.method public constructor <init>()V
.registers 1
invoke-direct {p0}, Ljadx/tests/api/SmaliTest;-><init>()V
return-void
.end method
.method private static call(Ljava/lang/String;)V
.registers 1
return-void
.end method
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