1616import soot .jimple .infoflow .methodSummary .data .provider .IMethodSummaryProvider ;
1717import soot .jimple .infoflow .methodSummary .data .summary .ClassMethodSummaries ;
1818import soot .jimple .infoflow .methodSummary .data .summary .ClassSummaries ;
19+ import soot .jimple .infoflow .util .ByReferenceBoolean ;
1920
2021/**
2122 * A resolver for finding all applicable summaries for a given method call
@@ -35,32 +36,44 @@ public SummaryResponse load(SummaryQuery query) throws Exception {
3536 final SootClass declaredClass = query .declaredClass ;
3637 final String methodSig = query .subsignature ;
3738 final ClassSummaries classSummaries = new ClassSummaries ();
38- boolean isClassSupported = false ;
39+ boolean directHit = false ;
40+ ByReferenceBoolean isClassSupported = new ByReferenceBoolean (false );
3941
4042 // Get the flows in the target method
4143 if (calleeClass != null )
42- isClassSupported = getSummaries (methodSig , classSummaries , calleeClass );
44+ directHit = getSummaries (methodSig , classSummaries , calleeClass , isClassSupported );
4345
4446 // If we haven't found any summaries, we look at the class from the declared
4547 // type at the call site
46- if (declaredClass != null && !isClassSupported )
47- isClassSupported = getSummaries (methodSig , classSummaries , declaredClass );
48+ if (declaredClass != null && !directHit )
49+ directHit = getSummaries (methodSig , classSummaries , declaredClass , isClassSupported );
4850
4951 // If we still don't have anything, we must try the hierarchy. Since this
5052 // best-effort approach can be fairly imprecise, it is our last resort.
51- if (!isClassSupported && calleeClass != null )
52- isClassSupported = getSummariesHierarchy (methodSig , classSummaries , calleeClass );
53- if (declaredClass != null && !isClassSupported )
54- isClassSupported = getSummariesHierarchy (methodSig , classSummaries , declaredClass );
55-
56- if (isClassSupported ) {
57- if (classSummaries . isEmpty ())
58- return SummaryResponse . EMPTY_BUT_SUPPORTED ;
59- return new SummaryResponse ( classSummaries , isClassSupported ) ;
60- } else
53+ if (!directHit && calleeClass != null )
54+ directHit = getSummariesHierarchy (methodSig , classSummaries , calleeClass , isClassSupported );
55+ if (declaredClass != null && !directHit )
56+ directHit = getSummariesHierarchy (methodSig , classSummaries , declaredClass , isClassSupported );
57+
58+ if (directHit && ! classSummaries . isEmpty ())
59+ return new SummaryResponse (classSummaries , true );
60+ else if ( directHit || isClassSupported . value )
61+ return SummaryResponse . EMPTY_BUT_SUPPORTED ;
62+ else
6163 return SummaryResponse .NOT_SUPPORTED ;
6264 }
6365
66+ private void updateClassExclusive (ByReferenceBoolean classSupported , SootClass sc , String subsig ) {
67+ if (classSupported .value )
68+ return ;
69+
70+ if (sc .getMethodUnsafe (subsig ) == null )
71+ return ;
72+
73+ ClassMethodSummaries cms = flows .getClassFlows (sc .getName ());
74+ classSupported .value |= cms != null && cms .isExclusiveForClass ();
75+ }
76+
6477 /**
6578 * Checks whether we have summaries for the given method signature in the given
6679 * class
@@ -70,27 +83,32 @@ public SummaryResponse load(SummaryQuery query) throws Exception {
7083 * @param clazz The class for which to look for summaries
7184 * @return True if summaries were found, false otherwise
7285 */
73- private boolean getSummaries (final String methodSig , final ClassSummaries summaries , SootClass clazz ) {
86+ private boolean getSummaries (final String methodSig , final ClassSummaries summaries , SootClass clazz ,
87+ ByReferenceBoolean classSupported ) {
7488 // Do we have direct support for the target class?
7589 if (summaries .merge (flows .getMethodFlows (clazz , methodSig )))
7690 return true ;
7791
7892 // Do we support any interface this class might have?
79- if (checkInterfaces (methodSig , summaries , clazz ))
93+ if (checkInterfaces (methodSig , summaries , clazz , classSupported ))
8094 return true ;
8195
96+ updateClassExclusive (classSupported , clazz , methodSig );
97+
98+ SootMethod targetMethod = clazz .getMethodUnsafe (methodSig );
8299 // If the target is abstract and we haven't found any flows,
83100 // we check for child classes
84- SootMethod targetMethod = clazz .getMethodUnsafe (methodSig );
85101 if (!clazz .isConcrete () || targetMethod == null || !targetMethod .isConcrete ()) {
86102 for (SootClass parentClass : getAllParentClasses (clazz )) {
87103 // Do we have support for the target class?
88104 if (summaries .merge (flows .getMethodFlows (parentClass , methodSig )))
89105 return true ;
90106
91107 // Do we support any interface this class might have?
92- if (checkInterfaces (methodSig , summaries , parentClass ))
108+ if (checkInterfaces (methodSig , summaries , parentClass , classSupported ))
93109 return true ;
110+
111+ updateClassExclusive (classSupported , parentClass , methodSig );
94112 }
95113 }
96114
@@ -107,7 +125,7 @@ private boolean getSummaries(final String methodSig, final ClassSummaries summar
107125 * @return True if summaries were found, false otherwise
108126 */
109127 private boolean getSummariesHierarchy (final String methodSig , final ClassSummaries summaries ,
110- SootClass clazz ) {
128+ SootClass clazz , ByReferenceBoolean classSupported ) {
111129 // Don't try to look up the whole Java hierarchy
112130 if (clazz .getName ().equals ("java.lang.Object" ))
113131 return false ;
@@ -126,9 +144,11 @@ private boolean getSummariesHierarchy(final String methodSig, final ClassSummari
126144 found ++;
127145
128146 // Do we support any interface this class might have?
129- if (checkInterfaces (methodSig , summaries , childClass ))
147+ if (checkInterfaces (methodSig , summaries , childClass , classSupported ))
130148 found ++;
131149
150+ updateClassExclusive (classSupported , childClass , methodSig );
151+
132152 // If we have too many summaries that could be applicable, we abort here to
133153 // avoid false positives
134154 if (found > MAX_HIERARCHY_DEPTH )
@@ -148,7 +168,8 @@ private boolean getSummariesHierarchy(final String methodSig, final ClassSummari
148168 * @param clazz The interface for which to look for summaries
149169 * @return True if summaries were found, false otherwise
150170 */
151- private boolean checkInterfaces (String methodSig , ClassSummaries summaries , SootClass clazz ) {
171+ private boolean checkInterfaces (String methodSig , ClassSummaries summaries , SootClass clazz ,
172+ ByReferenceBoolean classSupported ) {
152173 for (SootClass intf : clazz .getInterfaces ()) {
153174 // Directly check the interface
154175 if (summaries .merge (flows .getMethodFlows (intf , methodSig )))
@@ -158,6 +179,8 @@ private boolean checkInterfaces(String methodSig, ClassSummaries summaries, Soot
158179 // Do we have support for the interface?
159180 if (summaries .merge (flows .getMethodFlows (parent , methodSig )))
160181 return true ;
182+
183+ updateClassExclusive (classSupported , parent , methodSig );
161184 }
162185 }
163186
0 commit comments