fix: move instruction out of try/catch (#468)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
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"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
.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
|
||||
Reference in New Issue
Block a user