1010 ******************************************************************************/
1111package soot .jimple .infoflow .android .entryPointCreators ;
1212
13+ import java .util .AbstractCollection ;
1314import java .util .ArrayList ;
1415import java .util .Arrays ;
1516import java .util .Collection ;
@@ -142,6 +143,8 @@ public class AndroidEntryPointCreator extends AbstractAndroidEntryPointCreator i
142143 private SootMethod getIntentMethod ;
143144 private SootMethod setIntentMethod ;
144145
146+ private AbstractCollection <SootMethod > additionalMethods ;
147+
145148 /**
146149 * Creates a new instance of the {@link AndroidEntryPointCreator} class and
147150 * registers a list of classes to be automatically scanned for Android lifecycle
@@ -220,38 +223,10 @@ protected SootMethod createDummyMainInternal() {
220223 // Make sure that we don't have any leftover state
221224 // from previous runs
222225 reset ();
226+ additionalMethods = new HashSet <>();
223227
224228 logger .info (String .format ("Creating Android entry point for %d components..." , components .size ()));
225229
226- // For some weird reason unknown to anyone except the flying spaghetti
227- // monster, the onCreate() methods of content providers run even before
228- // the application object's onCreate() is called.
229- {
230- boolean hasContentProviders = false ;
231- NopStmt beforeContentProvidersStmt = Jimple .v ().newNopStmt ();
232- body .getUnits ().add (beforeContentProvidersStmt );
233- for (SootClass currentClass : components ) {
234- if (entryPointUtils .getComponentType (currentClass ) == ComponentType .ContentProvider ) {
235- // Create an instance of the content provider
236- Local localVal = generateClassConstructor (currentClass );
237- if (localVal == null )
238- continue ;
239- localVarsForClasses .put (currentClass , localVal );
240-
241- // Conditionally call the onCreate method
242- NopStmt thenStmt = Jimple .v ().newNopStmt ();
243- createIfStmt (thenStmt );
244- searchAndBuildMethod (AndroidEntryPointConstants .CONTENTPROVIDER_ONCREATE , localVal );
245- body .getUnits ().add (thenStmt );
246- hasContentProviders = true ;
247- }
248- }
249- // Jump back to the beginning of this section to overapproximate the
250- // order in which the methods are called
251- if (hasContentProviders )
252- createIfStmt (beforeContentProvidersStmt );
253- }
254-
255230 // If the application tag in the manifest specifies a appComponentFactory, it
256231 // needs to be called first
257232 initializeApplComponentFactory ();
@@ -262,10 +237,12 @@ protected SootMethod createDummyMainInternal() {
262237 Jimple j = Jimple .v ();
263238
264239 // due to app component factories, that could be another application class!
240+ // The application class gets instantiated first. Note that although it's
241+ // created now, it's onCreate method gets called *after*
242+ // all content providers.
265243 SootClass applicationClassUse = Scene .v ().getSootClass (AndroidEntryPointConstants .APPLICATIONCLASS );
266- ;
267- // If we have an application, we need to start it in the very beginning
268- if (applicationClass != null || applicationComponentFactoryClass != null ) {
244+ boolean generateApplicationCode = applicationClass != null || applicationComponentFactoryClass != null ;
245+ if (generateApplicationCode ) {
269246 if (applicationComponentFactoryClass != null ) {
270247 Local factory = generateClassConstructor (applicationComponentFactoryClass );
271248 SootMethodRef mrInstantiate = Scene .v ().makeMethodRef (
@@ -294,8 +271,10 @@ protected SootMethod createDummyMainInternal() {
294271 mrInstantiateClassLoader , Arrays .asList (classLoader , createApplicationInfo ())));
295272 body .getUnits ().add (instantiateCL );
296273
297- classLoaderField = createField (RefType .v ("java.lang.ClassLoader" ), "cl" );
298- instantiatorField = createField (RefType .v ("android.app.AppComponentFactory" ), "cl" );
274+ if (classLoaderField == null )
275+ classLoaderField = createField (RefType .v ("java.lang.ClassLoader" ), "cl" );
276+ if (instantiatorField == null )
277+ instantiatorField = createField (RefType .v ("android.app.AppComponentFactory" ), "cl" );
299278
300279 AssignStmt instantiate = j .newAssignStmt (applicationLocal , j .newVirtualInvokeExpr (factory ,
301280 mrInstantiate , Arrays .asList (classLoader , StringConstant .v (classAppl ))));
@@ -310,6 +289,41 @@ protected SootMethod createDummyMainInternal() {
310289 applicationClassUse = applicationClass ;
311290 }
312291 localVarsForClasses .put (applicationClass , applicationLocal );
292+ }
293+
294+ Map <SootClass , ContentProviderEntryPointCreator > cpComponents = new HashMap <>();
295+ // For some weird reason unknown to anyone except the flying spaghetti
296+ // monster, the onCreate() methods of content providers run even before
297+ // the application object's onCreate() is called (but after the creation of the
298+ // application).
299+ // See https://issuetracker.google.com/issues/36917845#comment4
300+ {
301+ boolean hasContentProviders = false ;
302+ NopStmt beforeContentProvidersStmt = Jimple .v ().newNopStmt ();
303+ body .getUnits ().add (beforeContentProvidersStmt );
304+ for (SootClass currentClass : components ) {
305+ if (entryPointUtils .getComponentType (currentClass ) == ComponentType .ContentProvider ) {
306+ // Create an instance of the content provider
307+ ContentProviderEntryPointCreator cpc = new ContentProviderEntryPointCreator (currentClass ,
308+ applicationClassUse , this .manifest , instantiatorField , classLoaderField ,
309+ componentToInfo .getComponentExchangeInfo ());
310+ SootMethod m = cpc .createInit ();
311+ Local cpLocal = generator .generateLocal (RefType .v (AndroidEntryPointConstants .CONTENTPROVIDERCLASS ));
312+ body .getUnits ().add (Jimple .v ().newAssignStmt (cpLocal , Jimple .v ().newStaticInvokeExpr (m .makeRef ())));
313+ localVarsForClasses .put (currentClass , cpLocal );
314+ cpComponents .put (currentClass , cpc );
315+
316+ hasContentProviders = true ;
317+ }
318+ }
319+ // Jump back to the beginning of this section to overapproximate the
320+ // order in which the methods are called
321+ if (hasContentProviders )
322+ createIfStmt (beforeContentProvidersStmt );
323+ }
324+
325+ // If we have an application, we need to start it in the very beginning
326+ if (generateApplicationCode ) {
313327 if (applicationLocal != null ) {
314328 boolean hasApplicationCallbacks = applicationCallbackClasses != null
315329 && !applicationCallbackClasses .isEmpty ();
@@ -395,6 +409,7 @@ protected SootMethod createDummyMainInternal() {
395409 // Generate the lifecycles for the different kinds of Android
396410 // classes
397411 AbstractComponentEntryPointCreator componentCreator = null ;
412+ List <Value > params = Collections .singletonList (NullConstant .v ());
398413 switch (componentType ) {
399414 case Activity :
400415 Map <SootClass , SootMethod > curActivityToFragmentMethod = new HashMap <>();
@@ -425,8 +440,9 @@ protected SootMethod createDummyMainInternal() {
425440 this .manifest , instantiatorField , classLoaderField , componentToInfo .getComponentExchangeInfo ());
426441 break ;
427442 case ContentProvider :
428- componentCreator = new ContentProviderEntryPointCreator (currentClass , applicationClassUse ,
429- this .manifest , instantiatorField , classLoaderField , componentToInfo .getComponentExchangeInfo ());
443+ componentCreator = cpComponents .get (currentClass );
444+ //We need to pass on the content provider instance
445+ params = Arrays .asList (NullConstant .v (), localVarsForClasses .get (currentClass ));
430446 break ;
431447 default :
432448 componentCreator = null ;
@@ -443,11 +459,11 @@ protected SootMethod createDummyMainInternal() {
443459 SootMethod lifecycleMethod = componentCreator .createDummyMain ();
444460 componentToInfo .put (currentClass , componentCreator .getComponentInfo ());
445461
462+ additionalMethods .addAll (componentCreator .getAdditionalMethods ());
446463 // dummyMain(component, intent)
447464 if (shouldAddLifecycleCall (currentClass )) {
448- body .getUnits ()
449- .add (Jimple .v ().newInvokeStmt (Jimple .v ().newStaticInvokeExpr (lifecycleMethod .makeRef (),
450- Collections .singletonList (NullConstant .v ()))));
465+ body .getUnits ().add (Jimple .v ()
466+ .newInvokeStmt (Jimple .v ().newStaticInvokeExpr (lifecycleMethod .makeRef (), params )));
451467 }
452468 }
453469
@@ -853,7 +869,10 @@ public void setFragments(MultiMap<SootClass, SootClass> fragments) {
853869
854870 @ Override
855871 public Collection <SootMethod > getAdditionalMethods () {
856- return componentToInfo .getLifecycleMethods ();
872+ List <SootMethod > r = new ArrayList <>(componentToInfo .getLifecycleMethods ());
873+ if (additionalMethods != null )
874+ r .addAll (additionalMethods );
875+ return r ;
857876 }
858877
859878 @ Override
0 commit comments