22
33import java .io .IOException ;
44import java .util .ArrayList ;
5+ import java .util .Collections ;
56import java .util .HashSet ;
67import java .util .Iterator ;
78import java .util .List ;
89import java .util .Map ;
910import java .util .Set ;
1011
12+ import heros .solver .Pair ;
1113import soot .MethodOrMethodContext ;
1214import soot .PackManager ;
15+ import soot .RefType ;
1316import soot .Scene ;
1417import soot .SceneTransformer ;
1518import soot .SootClass ;
@@ -45,22 +48,28 @@ public class DefaultCallbackAnalyzer extends AbstractCallbackAnalyzer implements
4548 private AndroidEntryPointUtils entryPointUtils = new AndroidEntryPointUtils ();
4649 private Set <IMemoryBoundedSolverStatusNotification > notificationListeners = new HashSet <>();
4750 private ISolverTerminationReason isKilled = null ;
51+ private MultiMap <SootClass , AndroidCallbackDefinition > viewCallbacks ;
4852
4953 public DefaultCallbackAnalyzer (InfoflowAndroidConfiguration config , Set <SootClass > entryPointClasses )
5054 throws IOException {
5155 super (config , entryPointClasses );
5256 }
5357
5458 public DefaultCallbackAnalyzer (InfoflowAndroidConfiguration config , Set <SootClass > entryPointClasses ,
55- String callbackFile ) throws IOException {
59+ MultiMap < SootClass , AndroidCallbackDefinition > viewCallbacks , String callbackFile ) throws IOException {
5660 super (config , entryPointClasses , callbackFile );
61+ this .viewCallbacks = viewCallbacks ;
5762 }
5863
5964 public DefaultCallbackAnalyzer (InfoflowAndroidConfiguration config , Set <SootClass > entryPointClasses ,
60- Set <String > androidCallbacks ) throws IOException {
65+ MultiMap <SootClass , AndroidCallbackDefinition > viewCallbacks , Set <String > androidCallbacks )
66+ throws IOException {
6167 super (config , entryPointClasses , androidCallbacks );
68+ this .viewCallbacks = viewCallbacks ;
6269 }
6370
71+ QueueReader <MethodOrMethodContext > reachableChangedListener ;
72+
6473 /**
6574 * Collects the callback methods for all Android default handlers implemented in
6675 * the source code. Note that this operation runs inside Soot, so this method
@@ -97,17 +106,31 @@ protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes")
97106 entryPointUtils .getLifecycleMethods (sc ));
98107
99108 // Check for callbacks registered in the code
100- analyzeRechableMethods (sc , methods );
109+ analyzeReachableMethods (sc , methods );
101110
102111 // Check for method overrides
103112 analyzeMethodOverrideCallbacks (sc );
104113 analyzeClassInterfaceCallbacks (sc , sc , sc );
105114 }
115+ reachableChangedListener = Scene .v ().getReachableMethods ().listener ();
106116 logger .info ("Callback analysis done." );
107117 } else {
108118 // Incremental mode, only process the worklist
109119 logger .info (String .format ("Running incremental callback analysis for %d components..." ,
110120 callbackWorklist .size ()));
121+ // Find the mappings between classes and layouts
122+ findClassLayoutMappings ();
123+
124+ MultiMap <SootMethod , SootClass > reverseViewCallbacks = new HashMultiMap <>();
125+ for (Pair <SootClass , AndroidCallbackDefinition > i : viewCallbacks )
126+ reverseViewCallbacks .put (i .getO2 ().getTargetMethod (), i .getO1 ());
127+ while (reachableChangedListener .hasNext ()) {
128+ SootMethod m = reachableChangedListener .next ().method ();
129+ Set <SootClass > o = reverseViewCallbacks .get (m );
130+ for (SootClass i : o ) {
131+ callbackWorklist .put (i , m );
132+ }
133+ }
111134
112135 MultiMap <SootClass , SootMethod > workList = new HashMultiMap <>(callbackWorklist );
113136 for (Iterator <SootClass > it = workList .keySet ().iterator (); it .hasNext ();) {
@@ -119,6 +142,10 @@ protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes")
119142 Set <SootMethod > callbacks = callbackWorklist .get (componentClass );
120143 callbackWorklist .remove (componentClass );
121144
145+ Set <SootClass > activityComponents = fragmentClassesRev .get (componentClass );
146+ if (activityComponents == null || activityComponents .isEmpty ())
147+ activityComponents = Collections .singleton (componentClass );
148+
122149 // Check whether we're already beyond the maximum number
123150 // of callbacks for the current component
124151 if (config .getCallbackConfig ().getMaxCallbacksPerComponent () > 0
@@ -130,15 +157,21 @@ protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes")
130157
131158 // Check for method overrides. The whole class might be new.
132159 analyzeMethodOverrideCallbacks (componentClass );
133- analyzeClassInterfaceCallbacks (componentClass , componentClass , componentClass );
160+ for (SootClass activityComponent : activityComponents ) {
161+ if (activityComponent == null )
162+ activityComponent = componentClass ;
163+ analyzeClassInterfaceCallbacks (componentClass , componentClass , activityComponent );
164+ }
134165
135166 // Collect all methods that we need to analyze
136167 List <MethodOrMethodContext > entryClasses = new ArrayList <>(callbacks .size ());
137- for (SootMethod sm : callbacks )
138- entryClasses .add (sm );
168+ for (SootMethod sm : callbacks ) {
169+ if (sm != null )
170+ entryClasses .add (sm );
171+ }
139172
140173 // Check for further callback declarations
141- analyzeRechableMethods (componentClass , entryClasses );
174+ analyzeReachableMethods (componentClass , entryClasses );
142175 }
143176 logger .info ("Incremental callback analysis done." );
144177 }
@@ -152,7 +185,7 @@ protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes")
152185 PackManager .v ().getPack ("wjtp" ).add (transform );
153186 }
154187
155- private void analyzeRechableMethods (SootClass lifecycleElement , List <MethodOrMethodContext > methods ) {
188+ private void analyzeReachableMethods (SootClass lifecycleElement , List <MethodOrMethodContext > methods ) {
156189 // Make sure to exclude all other edges in the callgraph except for the
157190 // edges start in the lifecycle methods we explicitly pass in
158191 ComponentReachableMethods rm = new ComponentReachableMethods (config , lifecycleElement , methods );
@@ -205,40 +238,53 @@ protected void checkAndAddFragment(SootClass componentClass, SootClass fragmentC
205238 }
206239 }
207240
241+ Iterator <MethodOrMethodContext > rmIterator ;
242+
208243 /**
209244 * Finds the mappings between classes and their respective layout files
210245 */
211246 private void findClassLayoutMappings () {
212- Iterator <MethodOrMethodContext > rmIterator = Scene .v ().getReachableMethods ().listener ();
247+ if (rmIterator == null )
248+ rmIterator = Scene .v ().getReachableMethods ().listener ();
213249 while (rmIterator .hasNext ()) {
214250 SootMethod sm = rmIterator .next ().method ();
251+
215252 if (!sm .isConcrete ())
216253 continue ;
217254 if (SystemClassHandler .v ().isClassInSystemPackage (sm .getDeclaringClass ().getName ()))
218255 continue ;
219-
220- for (Unit u : sm .retrieveActiveBody ().getUnits ())
256+ RefType fragmentType = RefType . v ( "android.app.Fragment" );
257+ for (Unit u : sm .retrieveActiveBody ().getUnits ()) {
221258 if (u instanceof Stmt ) {
222259 Stmt stmt = (Stmt ) u ;
223260 if (stmt .containsInvokeExpr ()) {
224261 InvokeExpr inv = stmt .getInvokeExpr ();
225- if (invokesSetContentView (inv ) || invokesInflate ( inv ) ) { // check
226- // also
227- // for
228- // inflate
229- // to
230- // look
231- // for
232- // the
233- // fragments
262+ if (invokesSetContentView (inv )) { // check
263+ // also
264+ // for
265+ // inflate
266+ // to
267+ // look
268+ // for
269+ // the
270+ // fragments
234271 for (Value val : inv .getArgs ()) {
235272 Integer intValue = valueProvider .getValue (sm , stmt , val , Integer .class );
236- if (intValue != null )
273+ if (intValue != null ) {
237274 this .layoutClasses .put (sm .getDeclaringClass (), intValue );
275+ }
276+
277+ }
278+ }
279+ if (invokesInflate (inv )) {
280+ Integer intValue = valueProvider .getValue (sm , stmt , inv .getArg (0 ), Integer .class );
281+ if (intValue != null ) {
282+ this .layoutClasses .put (sm .getDeclaringClass (), intValue );
238283 }
239284 }
240285 }
241286 }
287+ }
242288 }
243289 }
244290
0 commit comments