11package soot .jimple .infoflow .android .callbacks ;
22
33import java .util .Collection ;
4- import java .util .HashSet ;
4+ import java .util .Collections ;
55import java .util .Iterator ;
66import java .util .Set ;
7+ import java .util .concurrent .ConcurrentHashMap ;
78
9+ import soot .FastHierarchy ;
810import soot .Kind ;
911import soot .MethodOrMethodContext ;
1012import soot .RefType ;
1113import soot .Scene ;
1214import soot .SootClass ;
1315import soot .SootMethod ;
1416import soot .jimple .InstanceInvokeExpr ;
17+ import soot .jimple .InvokeExpr ;
1518import soot .jimple .infoflow .android .InfoflowAndroidConfiguration ;
1619import soot .jimple .infoflow .util .SystemClassHandler ;
20+ import soot .jimple .toolkits .callgraph .CallGraph ;
1721import soot .jimple .toolkits .callgraph .Edge ;
1822import soot .jimple .toolkits .callgraph .EdgePredicate ;
1923import soot .jimple .toolkits .callgraph .Filter ;
24+ import soot .jimple .toolkits .callgraph .ReachableMethods ;
2025import soot .jimple .toolkits .callgraph .Targets ;
2126import soot .util .queue .ChunkedQueue ;
2227import soot .util .queue .QueueReader ;
@@ -37,10 +42,11 @@ public class ComponentReachableMethods {
3742
3843 private final InfoflowAndroidConfiguration config ;
3944 private final SootClass originalComponent ;
40- private final Set <MethodOrMethodContext > set = new HashSet < MethodOrMethodContext >( );
45+ protected final Set <MethodOrMethodContext > set = Collections . newSetFromMap ( new ConcurrentHashMap <>() );
4146 private final ChunkedQueue <MethodOrMethodContext > reachables = new ChunkedQueue <MethodOrMethodContext >();
4247 private final QueueReader <MethodOrMethodContext > allReachables = reachables .reader ();
4348 private QueueReader <MethodOrMethodContext > unprocessedMethods ;
49+ private final SystemClassHandler systemClassHandler = SystemClassHandler .v ();
4450
4551 /**
4652 * Creates a new instance of the {@link ComponentReachableMethods} class
@@ -67,67 +73,79 @@ private void addMethods(Iterator<MethodOrMethodContext> methods) {
6773
6874 private void addMethod (MethodOrMethodContext m ) {
6975 // Filter out methods in system classes
70- if (!SystemClassHandler . v () .isClassInSystemPackage (m .method ().getDeclaringClass ())) {
76+ if (!systemClassHandler .isClassInSystemPackage (m .method ().getDeclaringClass ())) {
7177 if (set .add (m )) {
7278 reachables .add (m );
7379 }
7480 }
7581 }
7682
7783 public void update () {
78- while (unprocessedMethods .hasNext ()) {
79- MethodOrMethodContext m = unprocessedMethods .next ();
80- Filter filter = new Filter (new EdgePredicate () {
84+ final Scene sc = Scene .v ();
85+ final FastHierarchy fh = Scene .v ().getFastHierarchy ();
86+ final RefType runnable = RefType .v ("java.lang.Runnable" );
87+ final EdgePredicate predicate = new EdgePredicate () {
88+
89+ @ Override
90+ public boolean want (Edge e ) {
91+ if (e .kind () == Kind .CLINIT )
92+ return false ;
93+ else if (e .kind () == Kind .VIRTUAL ) {
94+ // We only filter calls to this.*
95+ InvokeExpr inv = e .srcStmt ().getInvokeExprUnsafe ();
96+ if (!e .src ().isStatic () && inv instanceof InstanceInvokeExpr ) {
97+ SootMethod refMethod = inv .getMethod ();
98+ InstanceInvokeExpr iinv = (InstanceInvokeExpr ) inv ;
99+ if (iinv .getBase () == e .src ().getActiveBody ().getThisLocal ()) {
100+
101+ // If our parent class P has an abstract
102+ // method foo() and the lifecycle
103+ // class L overrides foo(), make sure that
104+ // all calls to P.foo() in the
105+ // context of L only go to L.foo().
106+ SootClass calleeClass = refMethod .getDeclaringClass ();
107+ if (fh .isSubclass (originalComponent , calleeClass )) {
108+ SootClass targetClass = e .getTgt ().method ().getDeclaringClass ();
109+ return targetClass == originalComponent
110+ || fh .isSubclass (targetClass , originalComponent );
111+ }
112+ }
81113
82- @ Override
83- public boolean want (Edge e ) {
84- if (e .kind () == Kind .CLINIT )
114+ // We do not expect callback registrations in
115+ // any
116+ // calls to system classes
117+ if (systemClassHandler .isClassInSystemPackage (refMethod .getDeclaringClass ()))
118+ return false ;
119+ }
120+ } else if (config .getCallbackConfig ().getFilterThreadCallbacks ()) {
121+ // Check for thread call edges
122+ if (e .kind () == Kind .THREAD || e .kind () == Kind .EXECUTOR )
85123 return false ;
86- else if (e .kind () == Kind .VIRTUAL ) {
87- // We only filter calls to this.*
88- if (!e .src ().isStatic () && e .srcStmt ().getInvokeExpr () instanceof InstanceInvokeExpr ) {
89- SootMethod refMethod = e .srcStmt ().getInvokeExpr ().getMethod ();
90- InstanceInvokeExpr iinv = (InstanceInvokeExpr ) e .srcStmt ().getInvokeExpr ();
91- if (iinv .getBase () == e .src ().getActiveBody ().getThisLocal ()) {
92-
93- // If our parent class P has an abstract
94- // method foo() and the lifecycle
95- // class L overrides foo(), make sure that
96- // all calls to P.foo() in the
97- // context of L only go to L.foo().
98- SootClass calleeClass = refMethod .getDeclaringClass ();
99- if (Scene .v ().getFastHierarchy ().isSubclass (originalComponent , calleeClass )) {
100- SootClass targetClass = e .getTgt ().method ().getDeclaringClass ();
101- return targetClass == originalComponent
102- || Scene .v ().getFastHierarchy ().isSubclass (targetClass , originalComponent );
103- }
104- }
105124
106- // We do not expect callback registrations in
107- // any
108- // calls to system classes
109- if (SystemClassHandler .v ().isClassInSystemPackage (refMethod .getDeclaringClass ()))
110- return false ;
111- }
112- } else if (config .getCallbackConfig ().getFilterThreadCallbacks ()) {
113- // Check for thread call edges
114- if (e .kind () == Kind .THREAD || e .kind () == Kind .EXECUTOR )
125+ // Some apps have a custom layer for managing
126+ // threads,
127+ // so we need a more generic model
128+ if (e .tgt ().getName ().equals ("run" ))
129+ if (sc .getFastHierarchy ().canStoreType (e .tgt ().getDeclaringClass ().getType (), runnable ))
115130 return false ;
131+ }
132+ return true ;
133+ }
116134
117- // Some apps have a custom layer for managing
118- // threads,
119- // so we need a more generic model
120- if (e .tgt ().getName ().equals ("run" ))
121- if (Scene .v ().getFastHierarchy ().canStoreType (e .tgt ().getDeclaringClass ().getType (),
122- RefType .v ("java.lang.Runnable" )))
123- return false ;
124- }
125- return true ;
135+ };
136+ final CallGraph cg = sc .getCallGraph ();
137+
138+ while (unprocessedMethods .hasNext ()) {
139+ MethodOrMethodContext m = unprocessedMethods .next ();
140+ Iterator <Edge > of = cg .edgesOutOf (m );
141+ if (of != null && of .hasNext ()) {
142+ Filter filter = new Filter (predicate );
143+ Iterator <Edge > targets = filter .wrap (of );
144+ if (targets .hasNext ()) {
145+ addMethods (new Targets (targets ));
126146 }
147+ }
127148
128- });
129- Iterator <Edge > targets = filter .wrap (Scene .v ().getCallGraph ().edgesOutOf (m ));
130- addMethods (new Targets (targets ));
131149 }
132150 }
133151
@@ -159,4 +177,4 @@ public int size() {
159177 return set .size ();
160178 }
161179
162- }
180+ }
0 commit comments