Skip to content

Commit c2b2a41

Browse files
committed
StubDroid: set classSupported field to true if we have an identity summary
1 parent bae11fd commit c2b2a41

File tree

4 files changed

+60
-22
lines changed

4 files changed

+60
-22
lines changed

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/taintWrappers/resolvers/SummaryResolver.java

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import soot.jimple.infoflow.methodSummary.data.provider.IMethodSummaryProvider;
1717
import soot.jimple.infoflow.methodSummary.data.summary.ClassMethodSummaries;
1818
import 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

soot-infoflow-summaries/test/soot/jimple/infoflow/test/methodSummary/ApiClassClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,4 +320,11 @@ public void noPropagationOverUnhandledCallee() {
320320
overwrite(d);
321321
sink(d.stringField);
322322
}
323+
324+
public void identityIsStillAppliedOnUnhandledMethodButExclusiveClass() {
325+
Data d = new Data();
326+
d.stringField = stringSource();
327+
d.identity();
328+
sink(d.stringField);
329+
}
323330
}

soot-infoflow-summaries/test/soot/jimple/infoflow/test/methodSummary/Data.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,8 @@ public void setI(String i) {
5252
this.stringField = i;
5353
}
5454

55-
55+
public void identity() {
56+
// NO-OP but do something to make sure that this won't get removed by optimizations
57+
System.out.println("Hello World");
58+
}
5659
}

soot-infoflow-summaries/test/soot/jimple/infoflow/test/methodSummary/junit/SummaryTaintWrapperTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ public void noPropagationOverUnhandledCallee() {
237237
testNoFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void noPropagationOverUnhandledCallee()>");
238238
}
239239

240+
@Test(timeout = 30000)
241+
public void identityIsStillAppliedOnUnhandledMethodButExclusiveClass() {
242+
testFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void identityIsStillAppliedOnUnhandledMethodButExclusiveClass()>");
243+
}
244+
240245
@Test
241246
public void testAllSummaries() throws URISyntaxException, IOException {
242247
EagerSummaryProvider provider = new EagerSummaryProvider(TaintWrapperFactory.DEFAULT_SUMMARY_DIR);

0 commit comments

Comments
 (0)