[Soot-list] Problem Instrumenting Kotlin data class

Alessio Gambi alessio.gambi at uni-passau.de
Mon Mar 22 13:15:07 EDT 2021


Dear All,

I am facing a weird problem while instrumenting a Kotlin data class using soot [1].

The problem is that after instrumenting the class, the byte code verifier rejects the class.

The method causing this seems to be “copy” that contains those units:

r0 := @this: com.orgzly.android.util.Encoding
$r1 := @parameter0: java.lang.String
$r2 := @parameter1: java.lang.String
$r3 := @parameter2: java.lang.String
staticinvoke <kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>($r1, "used")
r0 = new com.orgzly.android.util.Encoding
specialinvoke r0.<com.orgzly.android.util.Encoding: void <init>(java.lang.String,java.lang.String,java.lang.String)>($r1, $r2, $r3)
return r0

The same method after the instrumentation looks like the one reported below (I simplified it), where the units marked with ** are the code injected via soot.

The instrumentations 
	- encapsulates all the parameters of method calls into generic arrays of objects
	- invokes a Monitor class to track method invocations (before/after) and captures return values
	- wraps the method with a generic try-catch-all where the catch block logs the captured exception before rethrowing it

Now the weirdness (IMHO) is that r0 is assigned first to @this and then to something different (r0 = new com.orgzly.android.util.Encoding).
This is part of the original code (see above), but I am afraid it might break the instrumented code because we pass r0 as parameter to other invocations in the catch block,
under the assumption it points to “this”, while in reality it points to another instance of the same type.
Consequently, the bytecode verifier reports the first call using it  in the catch block (staticinvoke <Monitor: void onAppMethodCaptureException)  as invalid (with type conflict)

Maybe someone has experiences something similar and/or can suggest a work around? Assuming this is indeed the problem, the only option I see at the moment
 is to assign the return of  r0 = new com.orgzly.android.util.Encoding to a fresh local variable (rX)

Any help is appreciated !

Best

— Dr. Alessio Gambi
Chair for SE 2
University of Passau


—————
[1] https://github.com/orgzly/orgzly-android/blob/master/app/src/main/java/com/orgzly/android/util/Encoding.kt <https://github.com/orgzly/orgzly-android/blob/master/app/src/main/java/com/orgzly/android/util/Encoding.kt>

INSTRUMENTED CODE:
                 r0 := @this: com.orgzly.android.util.Encoding
                 $r1 := @parameter0: java.lang.String
                 $r2 := @parameter1: java.lang.String
                 $r3 := @parameter2: java.lang.String
**               $r5 = newarray (java.lang.Object)[3]
**               $r5[0] = $r1
**               $r5[1] = $r2
**               $r5[2] = $r3
**               staticinvoke <Monitor: void onAppMethodCall(java.lang.String,java.lang.Object,java.lang.String,java.lang.Object[])>("com.orgzly", r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r5)
**               $r6 = newarray (java.lang.Object)[2]
**               $r6[0] = $r1
**               $r6[1] = "used"
**               staticinvoke <Monitor: void onLibMethodCall(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object[])>(null, "<kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r6)
                 staticinvoke <kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>($r1, "used")
**               staticinvoke <Monitor: void onLibMethodReturnNormally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(null, "<kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", null)

                 r0 = new com.orgzly.android.util.Encoding
                 specialinvoke r0.<com.orgzly.android.util.Encoding: void <init>(java.lang.String,java.lang.String,java.lang.String)>($r1, $r2, $r3)
**               staticinvoke <Monitor: void onAppMethodReturnNormally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", r0)
                 return r0

**               $r0 := @caughtexception
**               $r7 = $r0
**               staticinvoke <Monitor: void onAppMethodCaptureException(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r0)
**               $r4 = $r0
**               staticinvoke <Monitor: void onAppMethodThrowException(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r4)
**               staticinvoke <Monitor: void onAppMethodReturnExceptionally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r4)
**               throw $r4


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20210322/224b804a/attachment.html>


More information about the Soot-list mailing list