[Soot-list] Problem Instrumenting Kotlin data class

Alessio Gambi alessio.gambi at uni-passau.de
Tue Mar 23 13:01:46 EDT 2021


One follow up to this:

We cloned and rebuild soot from source, but commented out this line [1] inside DexBody.java, and this solved the problem.

Basically, we avoid that the LocalPacker transforms the jimple body to minimize the use of local variables.

I am not sure this is the best strategy in general, but I am also not sure how LocalPacker can be disabled without patching the code.

Maybe I should run some transformation after I inject the tracing code to ensure this local variable is not reused? Something like LocalSplitter?

Any thoughts are welcome.

Best


— Alessio

[1] https://github.com/soot-oss/soot/blob/59931576784b910a7d38f81910b7313aa2feafea/src/main/java/soot/dexpler/DexBody.java#L868

> On 23. Mar 2021, at 08:44, Alessio Gambi <alessio.gambi at uni-passau.de> wrote:
> 
> Hi Marc,
> 
> maybe you are right, but the same pattern of code works fine with other apps.
> 
> Best
> 
> — Alessio 
> 
>> On 22. Mar 2021, at 18:29, Marc Miltenberger <marcmiltenberger at gmail.com <mailto:marcmiltenberger at gmail.com>> wrote:
>> 
>> Hello Dr. Gambi,
>> 
>> I see one issue in this line:
>> $r0 := @caughtexception
>> 
>> This does not seem right since $r0 is of type com.orgzly.android.util.Encoding. This should actually be some sort of throwable.
>> 
>> Best regards,
>> Marc Miltenberger
>> 
>> 
>> 
>> Am Mo., 22. März 2021 um 18:24 Uhr schrieb Alessio Gambi <alessio.gambi at uni-passau.de <mailto:alessio.gambi at uni-passau.de>>:
>> 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
>> 
>> 
>> _______________________________________________
>> Soot-list mailing list
>> Soot-list at CS.McGill.CA <mailto:Soot-list at CS.McGill.CA>
>> https://mailman.CS.McGill.CA/mailman/listinfo/soot-list <https://mailman.cs.mcgill.ca/mailman/listinfo/soot-list>
> 
> _______________________________________________
> Soot-list mailing list
> Soot-list at CS.McGill.CA
> https://mailman.CS.McGill.CA/mailman/listinfo/soot-list

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20210323/648e8ac3/attachment-0001.html>


More information about the Soot-list mailing list