0

So I'm trying to insert a RuntimeException in soot and I've written a method to help me do just that:

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;
}

which is based on the examples found here.

and I try to use it like so:

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);
}

The problem now is ... no exception is thrown. Neither like this, nor when I replace the newNeExpr with a newEqExpr, nor when I remove the if-check altogether.

So what's the proper way of throwing this exception?

UPDATE

Example of generated check code (if I make an newEqExpr out of the newNeExpr, the ifnonnull will change to 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
User1291
  • 7,664
  • 8
  • 51
  • 108
  • Did you make sure `DEBUG_VERIFY_DATA_NOT_NULL` is true? Also, could you please post the generated classfile? – Antimony Dec 20 '17 at 15:35
  • @Antimony That's the first thing I checked. Also, see edit for the generated code. (I'm not at liberty of releasing the entire classfile, sorry, but I trust this should suffice?) – User1291 Dec 21 '17 at 08:42
  • I think it would help if you could post the generated Jimple code instead of the bytecode. – Eric Jan 07 '18 at 12:00

0 Answers0