1818import java .io .InputStreamReader ;
1919import java .io .Reader ;
2020import java .util .ArrayList ;
21+ import java .util .Collections ;
2122import java .util .HashMap ;
2223import java .util .HashSet ;
2324import java .util .Iterator ;
@@ -523,31 +524,27 @@ protected void analyzeMethodForFragmentTransaction(SootClass lifecycleElement, S
523524
524525 // first check if there is a Fragment manager, a fragment transaction
525526 // and a call to the add method which adds the fragment to the transaction
526- boolean isFragmentManager = false ;
527- boolean isFragmentTransaction = false ;
528- boolean isAddTransaction = false ;
527+ boolean isAddOrReplaceTransaction = false ;
529528 for (Unit u : method .getActiveBody ().getUnits ()) {
530529 Stmt stmt = (Stmt ) u ;
531530 if (stmt .containsInvokeExpr ()) {
532531 final String methodName = stmt .getInvokeExpr ().getMethod ().getName ();
533- if (methodName .equals ("getFragmentManager" ) || methodName .equals ("getSupportFragmentManager" ))
534- isFragmentManager = true ;
535- else if (methodName .equals ("beginTransaction" ))
536- isFragmentTransaction = true ;
537- else if (methodName .equals ("add" ) || methodName .equals ("replace" ))
538- isAddTransaction = true ;
532+ if (methodName .equals ("add" ) || methodName .equals ("replace" ))
533+ isAddOrReplaceTransaction = true ;
539534 else if (methodName .equals ("inflate" ) && stmt .getInvokeExpr ().getArgCount () > 1 ) {
540535 Value arg = stmt .getInvokeExpr ().getArg (0 );
541- Integer fragmentID = valueProvider .getValue (method , stmt , arg , Integer .class );
542- if (fragmentID != null )
543- fragmentIDs .put (lifecycleElement , fragmentID );
536+ Set <Integer > fragmentID = valueProvider .getValue (method , stmt , arg , Integer .class );
537+ if (fragmentID != null ) {
538+ for (int f : fragmentID )
539+ fragmentIDs .put (lifecycleElement , f );
540+ }
544541 }
545542 }
546543 }
547544
548545 // now get the fragment class from the second argument of the add method
549546 // from the transaction
550- if (isFragmentManager && isFragmentTransaction && isAddTransaction )
547+ if (isAddOrReplaceTransaction )
551548 for (Unit u : method .getActiveBody ().getUnits ()) {
552549 Stmt stmt = (Stmt ) u ;
553550 if (stmt .containsInvokeExpr ()) {
@@ -557,34 +554,56 @@ else if (methodName.equals("inflate") && stmt.getInvokeExpr().getArgCount() > 1)
557554
558555 // Make sure that we referring to the correct class and
559556 // method
560- isFragmentTransaction = scFragmentTransaction != null && Scene .v ().getFastHierarchy ()
557+ boolean isFragmentTransaction = scFragmentTransaction != null && Scene .v ().getFastHierarchy ()
561558 .canStoreType (iinvExpr .getBase ().getType (), scFragmentTransaction .getType ());
562559 isFragmentTransaction |= scSupportFragmentTransaction != null && Scene .v ().getFastHierarchy ()
563560 .canStoreType (iinvExpr .getBase ().getType (), scSupportFragmentTransaction .getType ());
564561 isFragmentTransaction |= scAndroidXFragmentTransaction != null && Scene .v ().getFastHierarchy ()
565562 .canStoreType (iinvExpr .getBase ().getType (), scAndroidXFragmentTransaction .getType ());
566- isAddTransaction = stmt .getInvokeExpr ().getMethod ().getName ().equals ("add" )
563+ isAddOrReplaceTransaction = stmt .getInvokeExpr ().getMethod ().getName ().equals ("add" )
567564 || stmt .getInvokeExpr ().getMethod ().getName ().equals ("replace" );
568565
569- if (isFragmentTransaction && isAddTransaction ) {
566+ if (isFragmentTransaction && isAddOrReplaceTransaction ) {
570567 // We take all fragments passed to the method
571568 for (int i = 0 ; i < stmt .getInvokeExpr ().getArgCount (); i ++) {
572569 Value br = stmt .getInvokeExpr ().getArg (i );
573570
574- // Is this a fragment?
575- if (br .getType () instanceof RefType ) {
576- RefType rt = (RefType ) br .getType ();
577- if (br instanceof ClassConstant )
578- rt = (RefType ) ((ClassConstant ) br ).toSootType ();
579-
580- boolean addFragment = scFragment != null
581- && Scene .v ().getFastHierarchy ().canStoreType (rt , scFragment .getType ());
582- addFragment |= scSupportFragment != null && Scene .v ().getFastHierarchy ()
583- .canStoreType (rt , scSupportFragment .getType ());
584- addFragment |= scAndroidXFragment != null && Scene .v ().getFastHierarchy ()
585- .canStoreType (rt , scAndroidXFragment .getType ());
586- if (addFragment )
587- checkAndAddFragment (method .getDeclaringClass (), rt .getSootClass ());
571+ Type pt = stmt .getInvokeExpr ().getMethodRef ().getParameterType (i );
572+ if (pt instanceof RefType ) {
573+ RefType rpt = (RefType ) pt ;
574+ //skip tag parameter
575+ if (rpt .getClassName ().equals ("java.lang.String" ))
576+ continue ;
577+ Set <Type > possibleTypes = Collections .emptySet ();
578+ if (((RefType ) pt ).getSootClass ().getName ().equals ("java.lang.Class" )) {
579+ Set <ClassConstant > ct = valueProvider .getValue (method , stmt , br ,
580+ ClassConstant .class );
581+ if (ct != null ) {
582+ possibleTypes = new HashSet <>();
583+ for (ClassConstant p : ct ) {
584+ possibleTypes .add ((RefType ) (p .toSootType ()));
585+ }
586+ }
587+
588+ } else {
589+ possibleTypes = valueProvider .getType (method , stmt , br );
590+ }
591+
592+ for (Type t : possibleTypes ) {
593+ if (t instanceof RefType ) {
594+ RefType frt = (RefType ) t ;
595+ // Is this a fragment?
596+ boolean addFragment = scFragment != null && Scene .v ().getFastHierarchy ()
597+ .canStoreType (frt , scFragment .getType ());
598+ addFragment |= scSupportFragment != null && Scene .v ().getFastHierarchy ()
599+ .canStoreType (frt , scSupportFragment .getType ());
600+ addFragment |= scAndroidXFragment != null && Scene .v ().getFastHierarchy ()
601+ .canStoreType (frt , scAndroidXFragment .getType ());
602+ if (addFragment )
603+ checkAndAddFragment (method .getDeclaringClass (), frt .getSootClass ());
604+ }
605+ }
606+
588607 }
589608 }
590609 }
0 commit comments