Skip to content

CModifyExpressionValue

Lenni0451 edited this page Mar 21, 2024 · 1 revision

The CModifyExpressionValue annotation can be used to modify the value of an expression.
Expression can be method invokes, field accesses or new object creations.

The value type is:

  • The return type of a method invoke
  • The type of a field
  • The type of a newly created object

Method signature

The transformer method needs to have the value type as the only parameter and return value.
When injecting into a static method, the transformer method also needs to be static and vice versa.

//Injecting into a static method
@CModifyExpressionValue(method = "method", ...)
public static String transform(final String value)

//Injecting into a non-static method
@CModifyExpressionValue(method = "otherMethod", ...)
public int transform(final int value)

Targets

The target field of the CModifyExpressionValue annotation specifies the redirected method/field/constructor.
Check out the CTarget page for more information about the different targets.
Also, check out CSlice for more information about how slices work.

Targeting multiple methods

The method field can be an array of strings to target multiple methods.
The transformer method needs to be compatible with all targeted methods.

@CModifyExpressionValue(method = {"method1", "method2"}, ...)
public String transform(final String value)

Examples

Original method:

public void method() {
    field = "Test";
    System.out.println(field);

    PrintStream ps = new PrintStream(new FileOutputStream("test.txt"));
    ps.println(getField());
    ps.close();
}

Modifying a field access

Transformer method:

@CModifyExpressionValue(method = "main", target = @CTarget(value = "FIELD", target = "LTest;field:Ljava/lang/String;"))
private static String transform(final String value) {
    return value.toUpperCase();
}

Injected code:

public void method() {
    field = transform("Test");
    System.out.println(transform(field));

    PrintStream ps = new PrintStream(new FileOutputStream("test.txt"));
    ps.println(getField());
    ps.close();
}

Modifying a method invoke

Transformer method:

@CModifyExpressionValue(method = "main", target = @CTarget(value = "INVOKE", target = "LTest;getField()Ljava/lang/String;"))
private static Object modifyInvoke(final String value) {
    return value.toLowerCase();
}

Injected code:

public void method() {
    field = "Test";
    System.out.println(field);

    PrintStream ps = new PrintStream(new FileOutputStream("test.txt"));
    ps.println(transform(getField()));
    ps.close();
}

Modifying a new object creation

Transformer method:

@CModifyExpressionValue(method = "main", target = @CTarget(value = "NEW", target = "java/io/PrintStream"))
private static PrintStream modifyNew(final PrintStream value) {
    value.close();
    return new PrintStream(new FileOutputStream("test2.txt"));
}

Injected code:

public void method() {
    field = "Test";
    System.out.println(field);

    PrintStream ps = transform(new PrintStream(new FileOutputStream("test.txt")));
    ps.println(getField());
    ps.close();
}