添加一个新的RuntimeException

时间:2017-12-20 14:56:50

标签: java bytecode instrumentation bytecode-manipulation soot

所以我试图在烟灰中插入一个RuntimeException,并且我已经写了一个方法来帮助我做到这一点:

private static final RefType STRING_TYPE = RefType.v("java.lang.String");
private static final RefType ERROR_TYPE = RefType.v("java.lang.Error");
/**
 * Given an error message and a method body, constructs stmts necessary for throwing a Runtime Exception.
 * @param errMsg the error message
 * @param body the body from which the exception will be thrown
 * @return the statements that will throw the runtime exception when executed
 */
public List<Stmt> runtimeException(String errMsg, Body body) {
    List<Stmt> stmts = new LinkedList<>();

    LocalGenerator lg = new LocalGenerator(body);
    Local exceptionLocal = lg.generateLocal(ERROR_TYPE);

    stmts.add(
            Jimple.v().newAssignStmt(
                    exceptionLocal,
                    Jimple.v().newNewExpr(ERROR_TYPE)
            )
    );

    SootMethodRef exceptionInit = ERROR_TYPE.getSootClass().getMethod("<init>", Collections.singletonList((Type)STRING_TYPE)).makeRef();

    stmts.add(
            Jimple.v().newInvokeStmt(
                    Jimple.v().newSpecialInvokeExpr(
                            exceptionLocal,
                            exceptionInit,
                            StringConstant.v(errMsg)

                    )
            )
    );

    stmts.add(Jimple.v().newThrowStmt(exceptionLocal));

    return stmts;
}

基于找到的示例here

我试着像这样使用它:

Stmt stmt = ...;
List<Stmt> stmts = new LinkedList<>();
Local dataLocal;
boolean DEBUG_VERIFY_DATA_NOT_NULL = True;

//... (fill ``stmts`` with statements to insert after ``stmt``)

UnitBox errorSkipBox;
Stmt skipTarget;
if(DEBUG_VERIFY_DATA_NOT_NULL) {
    String errMsg = "data is null but shouldn't be";

    errorSkipBox = Jimple.v().newStmtBox(null);

    stmts.add(
            Jimple.v().newAssignStmt(
                    dataLocal,
                    Jimple.v().newInstanceFieldRef(thisRef,dataField.makeRef())
            )
    );
    stmts.add(
            Jimple.v().newIfStmt(
                    Jimple.v().newNeExpr(
                            dataLocal,
                            NullConstant.v()
                    ),
                    errorSkipBox

            )
    );
    stmts.addAll(SootUtil.v().runtimeException(errMsg,body));
    skipTarget = Jimple.v().newNopStmt();
    stmts.add(skipTarget);
}

units.insertAfter(stmts,stmt);

if (DEBUG_VERIFY_DATA_NOT_NULL){
    errorSkipBox.setUnit(skipTarget);
}

现在的问题是......没有抛出任何异常。 既不是这样,也不是我用newNeExpr替换newEqExpr,也不是完全删除if-check。

那么抛出​​这个异常的正确方法是什么?

更新

生成的支票代码示例(如果我从newEqExpr中提出newNeExprifnonnull将更改为ifnull):

parc.MyClass(parc.lang.Class<? extends T>, boolean, java.lang.String, java.lang.String...);
descriptor: (Lparc/some/Thing;Lparc/lang/Class;ZLjava/lang/String;[Ljava/lang/String;)V
flags: ACC_VARARGS
Code:
  stack=2, locals=7, args_size=6
     0: new           #43                 // class parc/lang/Data
     3: astore        6
     5: aload_0
     6: invokespecial #46                 // Method java/lang/Object."<init>":()V
     9: aload_0
    10: aload         6
    12: putfield      #48                 // Field data:Lparc/lang/Data;
    15: aload_0
    16: getfield      #48                 // Field data:Lparc/lang/Data;
    19: astore        6
    21: aload         6
    23: ifnonnull     41
    26: new           #50                 // class java/lang/Error
    29: astore        6
    31: aload         6
    33: ldc           #52                 // String data is null but shouldn't be
    35: invokespecial #55                 // Method java/lang/Error."<init>":(Ljava/lang/String;)V
    38: aload         6
    40: athrow
    41: nop

    // ...

    93: return
  LineNumberTable:
    line 19: 5
    line 20: 50
    line 21: 55
    line 22: 60
    line 23: 66
    line 23: 73
    line 23: 80
    line 23: 87
    line 24: 93
  StackMapTable: number_of_entries = 1
    frame_type = 255 /* full_frame */
      offset_delta = 41
      locals = [ class parc/MyClass, class parc/some/Thing, class parc/lang/Class, int, class java/lang/String, class "[Ljava/lang/String;", class parc/lang/Data ]
      stack = []
Signature: #276                         // (Lparc/lang/Class<+TT;>;ZLjava/lang/String;[Ljava/lang/String;)V

0 个答案:

没有答案