Hi, it seems like Flowdroid is not deterministic. Running the same analysis (for the same APK) reports a different set of sources and sinks. For example, I am running Flowdroid with its "pro-performace" configuration (using EasyTaintWrapper)
java -jar Flowdroid.jar -apk /path/to/apk.apk -p ~/Android/Sdk/platforms/ -tw easy -t tmp/flowdroid-workspace/EasyTaintWrapperSource.txt -s /home/clod/tmp/flowdroid-workspace/general_source_sinks.txt -ne -af -al 3 -ca FAST -nc -ns -o out.xml
and I get the following two runs:
[main] INFO soot.jimple.infoflow.memory.MemoryWarningSystem - Shutting down the memory warning system...
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Memory consumption after path building: 164 MB
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Path reconstruction took 1 seconds
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int e(java.lang.String,java.lang.String,java.lang.Throwable)>($r0, $r1, $r2) in method <com.startapp.android.publish.h.l: void b(java.lang.String,int,java.lang.String,java.lang.Throwable)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getCid()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r6 = virtualinvoke $r2.<android.location.LocationManager: android.location.Location getLastKnownLocation(java.lang.String)>($r5) in method <com.startapp.android.publish.h.k: android.location.Location a(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLatitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getLac()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r7 = virtualinvoke $r6.<android.net.wifi.WifiInfo: java.lang.String getSSID()>() in method <com.startapp.android.publish.model.BaseRequest: void fillWifiDetails(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLongitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int v(java.lang.String,java.lang.String,java.lang.Throwable)>($r0, $r1, $r2) in method <com.startapp.android.publish.h.l: void b(java.lang.String,int,java.lang.String,java.lang.Throwable)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getCid()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r6 = virtualinvoke $r2.<android.location.LocationManager: android.location.Location getLastKnownLocation(java.lang.String)>($r5) in method <com.startapp.android.publish.h.k: android.location.Location a(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLatitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getLac()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r7 = virtualinvoke $r6.<android.net.wifi.WifiInfo: java.lang.String getSSID()>() in method <com.startapp.android.publish.model.BaseRequest: void fillWifiDetails(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLongitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r9.<java.io.Writer: void write(char[],int,int)>($r10, 0, $i0) in method <com.startapp.android.publish.h.n: boolean a(android.content.Context,java.lang.String,java.util.Map,java.lang.StringBuilder)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r8 = virtualinvoke $r5.<java.net.HttpURLConnection: java.io.InputStream getInputStream()>() in method <com.startapp.android.publish.h.n: boolean a(android.content.Context,java.lang.String,java.util.Map,java.lang.StringBuilder)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r7.<java.io.ByteArrayOutputStream: void write(byte[])>($r5) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.io.InputStream,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>($r1, $r0) in method <com.heyzap.internal.Logger: void debug(java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r0.<com.heyzap.house.abstr.AbstractActivity: android.content.Intent getIntent()>() in method <com.heyzap.house.abstr.AbstractActivity: void onCreate(android.os.Bundle)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Data flow solver took 5 seconds. Maximum memory consumption: 143 MB
[main] INFO soot.jimple.infoflow.android.SetupApplication - Found 9 leaks
and, for instance:
[main] INFO soot.jimple.infoflow.memory.MemoryWarningSystem - Shutting down the memory warning system...
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Memory consumption after path building: 165 MB
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Path reconstruction took 2 seconds
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r9.<java.io.Writer: void write(char[],int,int)>($r10, 0, $i0) in method <com.startapp.android.publish.h.n: boolean a(android.content.Context,java.lang.String,java.util.Map,java.lang.StringBuilder)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r8 = virtualinvoke $r5.<java.net.HttpURLConnection: java.io.InputStream getInputStream()>() in method <com.startapp.android.publish.h.n: boolean a(android.content.Context,java.lang.String,java.util.Map,java.lang.StringBuilder)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int e(java.lang.String,java.lang.String,java.lang.Throwable)>($r0, $r1, $r2) in method <com.startapp.android.publish.h.l: void b(java.lang.String,int,java.lang.String,java.lang.Throwable)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getCid()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r6 = virtualinvoke $r2.<android.location.LocationManager: android.location.Location getLastKnownLocation(java.lang.String)>($r5) in method <com.startapp.android.publish.h.k: android.location.Location a(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLatitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getLac()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r7 = virtualinvoke $r6.<android.net.wifi.WifiInfo: java.lang.String getSSID()>() in method <com.startapp.android.publish.model.BaseRequest: void fillWifiDetails(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLongitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int v(java.lang.String,java.lang.String,java.lang.Throwable)>($r0, $r1, $r2) in method <com.startapp.android.publish.h.l: void b(java.lang.String,int,java.lang.String,java.lang.Throwable)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getCid()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r6 = virtualinvoke $r2.<android.location.LocationManager: android.location.Location getLastKnownLocation(java.lang.String)>($r5) in method <com.startapp.android.publish.h.k: android.location.Location a(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLatitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $i0 = virtualinvoke $r5.<android.telephony.gsm.GsmCellLocation: int getLac()>() in method <com.startapp.android.publish.model.BaseRequest: void fillNetworkOperatorDetails(android.content.Context,android.telephony.TelephonyManager)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r7 = virtualinvoke $r6.<android.net.wifi.WifiInfo: java.lang.String getSSID()>() in method <com.startapp.android.publish.model.BaseRequest: void fillWifiDetails(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $d0 = virtualinvoke $r5.<android.location.Location: double getLongitude()>() in method <com.startapp.android.publish.model.GetAdRequest: void fillLocationDetails(com.startapp.android.publish.model.AdPreferences,android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r5.<java.io.ByteArrayOutputStream: void write(byte[])>($r6) in method <com.heyzap.http.SimpleMultipartEntity: void addPart(java.lang.String,java.lang.String,java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>($r1, $r0) in method <com.heyzap.internal.Logger: void debug(java.lang.String)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r0.<com.heyzap.house.abstr.AbstractActivity: android.content.Intent getIntent()>() in method <com.heyzap.house.abstr.AbstractActivity: void onCreate(android.os.Bundle)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r5 = virtualinvoke $r3.<java.util.Locale: java.lang.String getCountry()>() in method <com.heyzap.internal.Utils: java.util.HashMap extraParams(android.content.Context)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Data flow solver took 5 seconds. Maximum memory consumption: 144 MB
[main] INFO soot.jimple.infoflow.android.SetupApplication - Found 8 leaks
It varies with multiple runs. I have tried different configurations and all of them at some point present the same issue (the more precise, the rarer it is). Is non-determinism to be expected? I know there was an issue similar to this at some point in the past (https://github.com/secure-software-engineering/soot-infoflow-android/issues/31). It is somehow related?
The following is the SHA256 of the apk I am analysing: 9E4E75F510F76C4E4376A9AD6FD01843EA3F0F53CB9B3AEBDD3EBC6DC0A72C1D
Hi, it seems like Flowdroid is not deterministic. Running the same analysis (for the same APK) reports a different set of sources and sinks. For example, I am running Flowdroid with its "pro-performace" configuration (using EasyTaintWrapper)
java -jar Flowdroid.jar -apk /path/to/apk.apk -p ~/Android/Sdk/platforms/ -tw easy -t tmp/flowdroid-workspace/EasyTaintWrapperSource.txt -s /home/clod/tmp/flowdroid-workspace/general_source_sinks.txt -ne -af -al 3 -ca FAST -nc -ns -o out.xmland I get the following two runs:
and, for instance:
It varies with multiple runs. I have tried different configurations and all of them at some point present the same issue (the more precise, the rarer it is). Is non-determinism to be expected? I know there was an issue similar to this at some point in the past (https://github.com/secure-software-engineering/soot-infoflow-android/issues/31). It is somehow related?
The following is the SHA256 of the apk I am analysing:
9E4E75F510F76C4E4376A9AD6FD01843EA3F0F53CB9B3AEBDD3EBC6DC0A72C1D