Skip to content

Commit a6d6913

Browse files
committed
Add attachBaseContext support and optionally do not exclude stub methods in callback analyzer
1 parent f3d6eb2 commit a6d6913

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed

soot-infoflow-android/src/soot/jimple/infoflow/android/InfoflowAndroidConfiguration.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ public static class CallbackConfiguration {
320320
private int maxCallbackAnalysisDepth = -1;
321321
private boolean serializeCallbacks = false;
322322
private String callbacksFile = "";
323+
private boolean excludeStubsFromCallGraph = true;
323324

324325
/**
325326
* Copies the settings of the given configuration into this configuration object
@@ -335,6 +336,7 @@ public void merge(CallbackConfiguration cbConfig) {
335336
this.maxCallbackAnalysisDepth = cbConfig.maxCallbackAnalysisDepth;
336337
this.serializeCallbacks = cbConfig.serializeCallbacks;
337338
this.callbacksFile = cbConfig.callbacksFile;
339+
this.excludeStubsFromCallGraph = cbConfig.excludeStubsFromCallGraph;
338340
}
339341

340342
/**
@@ -510,6 +512,22 @@ public void setCallbacksFile(String callbacksFile) {
510512
this.callbacksFile = callbacksFile;
511513
}
512514

515+
/**
516+
* Returns whether FlowDroid should exclude stub methods when computing the call graph
517+
* @return true if stubs should be excluded
518+
*/
519+
public boolean getExcludeStubsFromCallGraph() {
520+
return excludeStubsFromCallGraph;
521+
}
522+
523+
/**
524+
* Sets whether FlowDroid should exclude stub methods when computing the call graph
525+
* @param value true if stubs should be excluded
526+
*/
527+
public void setExcludeStubsFromCallGraph(boolean value) {
528+
this.excludeStubsFromCallGraph = value;
529+
}
530+
513531
@Override
514532
public int hashCode() {
515533
final int prime = 31;
@@ -522,6 +540,7 @@ public int hashCode() {
522540
result = prime * result + maxCallbackAnalysisDepth;
523541
result = prime * result + maxCallbacksPerComponent;
524542
result = prime * result + (serializeCallbacks ? 1231 : 1237);
543+
result = prime * result + (excludeStubsFromCallGraph ? 1231 : 1237);
525544
return result;
526545
}
527546

@@ -553,6 +572,8 @@ public boolean equals(Object obj) {
553572
return false;
554573
if (serializeCallbacks != other.serializeCallbacks)
555574
return false;
575+
if (excludeStubsFromCallGraph != other.excludeStubsFromCallGraph)
576+
return false;
556577
return true;
557578
}
558579

soot-infoflow-android/src/soot/jimple/infoflow/android/callbacks/AbstractCallbackAnalyzer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ protected void analyzeMethodOverrideCallbacks(SootClass sootClass) {
846846
for (SootClass parentClass : Scene.v().getActiveHierarchy().getSuperclassesOf(sootClass)) {
847847
if (SystemClassHandler.v().isClassInSystemPackage(parentClass))
848848
for (SootMethod sm : parentClass.getMethods())
849-
if (!sm.isConstructor())
849+
if (!sm.isConstructor() && (sm.isProtected() || sm.isPublic()) && !sm.isStatic())
850850
systemMethods.put(sm.getSubSignature(), sm);
851851
}
852852

@@ -957,7 +957,8 @@ protected boolean checkAndAddMethod(SootMethod method, SootMethod parentMethod,
957957
return false;
958958

959959
// Skip empty methods
960-
if (method.isConcrete() && isEmpty(method.retrieveActiveBody()))
960+
if (config.getCallbackConfig().getExcludeStubsFromCallGraph() && method.isConcrete()
961+
&& isEmpty(method.retrieveActiveBody()))
961962
return false;
962963

963964
// Skip constructors

soot-infoflow-android/src/soot/jimple/infoflow/android/entryPointCreators/AndroidEntryPointConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ public class AndroidEntryPointConstants {
194194
private static final String[] serviceConnectionMethods = { SERVICECONNECTION_ONSERVICECONNECTED,
195195
SERVICECONNECTION_ONSERVICEDISCONNECTED };
196196
private static final List<String> serviceConnectionMethodList = Arrays.asList(serviceConnectionMethods);
197+
public static final String ATTACH_BASE_CONTEXT = "void attachBaseContext(android.content.Context)";
198+
public static final String CONTEXT_WRAPPER = "android.content.ContextWrapper";
197199
/*
198200
* ========================================================================
199201
*/

soot-infoflow-android/src/soot/jimple/infoflow/android/entryPointCreators/AndroidEntryPointCreator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,12 @@ protected SootMethod createDummyMainInternal() {
293293
localVarsForClasses.put(applicationClass, applicationLocal);
294294
}
295295

296+
body.getUnits()
297+
.add(j.newInvokeStmt(j.newVirtualInvokeExpr(applicationLocal,
298+
Scene.v().makeMethodRef(
299+
Scene.v().getSootClassUnsafe(AndroidEntryPointConstants.CONTEXT_WRAPPER),
300+
AndroidEntryPointConstants.ATTACH_BASE_CONTEXT, false))));
301+
296302
Map<SootClass, ContentProviderEntryPointCreator> cpComponents = new HashMap<>();
297303
// For some weird reason unknown to anyone except the flying spaghetti
298304
// monster, the onCreate() methods of content providers run even before

soot-infoflow-android/src/soot/jimple/infoflow/android/entryPointCreators/components/ActivityEntryPointCreator.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ protected void generateComponentLifecycle() {
9595
localVarsForClasses.put(sc, callbackLocal);
9696
}
9797

98-
// 1. onCreate:
98+
// 1. attachBaseContext
99+
searchAndBuildMethod(AndroidEntryPointConstants.ATTACH_BASE_CONTEXT, applicationLocal);
100+
101+
// 2. onCreate:
99102
{
100103
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONCREATE, thisLocal);
101104
for (SootClass callbackClass : this.activityLifecycleCallbacks.keySet()) {
@@ -118,7 +121,7 @@ protected void generateComponentLifecycle() {
118121
}
119122
}
120123

121-
// 2. onStart:
124+
// 3. onStart:
122125
Stmt onStartStmt;
123126
{
124127
onStartStmt = searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONSTART, thisLocal);
@@ -147,7 +150,7 @@ protected void generateComponentLifecycle() {
147150
}
148151
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONPOSTCREATE, thisLocal);
149152

150-
// 3. onResume:
153+
// 4. onResume:
151154
Stmt onResumeStmt = Jimple.v().newNopStmt();
152155
body.getUnits().add(onResumeStmt);
153156
{
@@ -173,7 +176,7 @@ protected void generateComponentLifecycle() {
173176
createIfStmt(startWhileStmt);
174177
}
175178

176-
// 4. onPause:
179+
// 5. onPause:
177180
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONPAUSE, thisLocal);
178181
for (SootClass callbackClass : this.activityLifecycleCallbacks.keySet()) {
179182
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITYLIFECYCLECALLBACK_ONACTIVITYPAUSED,
@@ -191,7 +194,7 @@ protected void generateComponentLifecycle() {
191194
createIfStmt(onResumeStmt);
192195
// createIfStmt(onCreateStmt); // no, the process gets killed in between
193196

194-
// 5. onStop:
197+
// 6. onStop:
195198
Stmt onStop = searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONSTOP, thisLocal);
196199
boolean hasAppOnStop = false;
197200
for (SootClass callbackClass : this.activityLifecycleCallbacks.keySet()) {
@@ -209,11 +212,11 @@ protected void generateComponentLifecycle() {
209212
createIfStmt(stopToDestroyStmt);
210213
// createIfStmt(onCreateStmt); // no, the process gets killed in between
211214

212-
// 6. onRestart:
215+
// 7. onRestart:
213216
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONRESTART, thisLocal);
214217
body.getUnits().add(Jimple.v().newGotoStmt(onStartStmt)); // jump to onStart()
215218

216-
// 7. onDestroy
219+
// 8. onDestroy
217220
body.getUnits().add(stopToDestroyStmt);
218221
searchAndBuildMethod(AndroidEntryPointConstants.ACTIVITY_ONDESTROY, thisLocal);
219222
for (SootClass callbackClass : this.activityLifecycleCallbacks.keySet()) {

soot-infoflow-android/src/soot/jimple/infoflow/android/entryPointCreators/components/ServiceEntryPointCreator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ public ServiceEntryPointCreator(SootClass component, SootClass applicationClass,
4040

4141
@Override
4242
protected void generateComponentLifecycle() {
43-
// 1. onCreate:
43+
44+
// 1. attachBaseContext
45+
searchAndBuildMethod(AndroidEntryPointConstants.ATTACH_BASE_CONTEXT, thisLocal);
46+
47+
// 2. onCreate:
4448
searchAndBuildMethod(AndroidEntryPointConstants.SERVICE_ONCREATE, thisLocal);
4549

4650
// service has two different lifecycles:
4751
// lifecycle1:
48-
// 2. onStart:
52+
// 3. onStart:
4953
searchAndBuildMethod(AndroidEntryPointConstants.SERVICE_ONSTART1, thisLocal);
5054

5155
// onStartCommand can be called an arbitrary number of times, or never

0 commit comments

Comments
 (0)