@@ -8,6 +8,7 @@ private import semmle.code.csharp.commons.Collections as Collections
8
8
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
9
9
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
10
10
private import semmle.code.csharp.frameworks.system.linq.Expressions
11
+ private import semmle.code.csharp.frameworks.System
11
12
import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
12
13
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
13
14
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
@@ -35,12 +36,23 @@ private predicate irrelevantAccessor(CS::Accessor a) {
35
36
}
36
37
37
38
private predicate isUninterestingForModels ( Callable api ) {
38
- api .getDeclaringType ( ) .getNamespace ( ) .getFullName ( ) = "" or
39
- api instanceof CS:: ConversionOperator or
40
- api instanceof Util:: MainMethod or
41
- api instanceof CS:: Destructor or
42
- api instanceof CS:: AnonymousFunctionExpr or
43
- api .( CS:: Constructor ) .isParameterless ( ) or
39
+ api .getDeclaringType ( ) .getNamespace ( ) .getFullName ( ) = ""
40
+ or
41
+ api instanceof CS:: ConversionOperator
42
+ or
43
+ api instanceof Util:: MainMethod
44
+ or
45
+ api instanceof CS:: Destructor
46
+ or
47
+ api instanceof CS:: AnonymousFunctionExpr
48
+ or
49
+ api .( CS:: Constructor ) .isParameterless ( )
50
+ or
51
+ exists ( Type decl | decl = api .getDeclaringType ( ) |
52
+ decl instanceof SystemObjectClass or
53
+ decl instanceof SystemValueTypeClass
54
+ )
55
+ or
44
56
// Disregard properties that have both a get and a set accessor,
45
57
// which implicitly means auto implemented properties.
46
58
irrelevantAccessor ( api )
@@ -53,18 +65,26 @@ private predicate relevant(Callable api) {
53
65
not isUninterestingForModels ( api )
54
66
}
55
67
56
- private predicate hasManualModel ( Callable api ) {
57
- api = any ( FlowSummaryImpl:: Public:: SummarizedCallable sc | sc .applyManualModel ( ) ) or
58
- api = any ( FlowSummaryImpl:: Public:: NeutralSummaryCallable sc | sc .hasManualModel ( ) )
68
+ private Callable getARelevantOverrideeOrImplementee ( Overridable m ) {
69
+ m .overridesOrImplements ( result ) and relevant ( result )
59
70
}
60
71
61
72
/**
62
- * Holds if it is relevant to generate models for `api`.
73
+ * Gets the super implementation of `m` if it is relevant.
74
+ * If such a super implementation does not exist, returns `m` if it is relevant.
63
75
*/
64
- private predicate isRelevantForModels ( Callable api ) {
65
- relevant ( api ) and
66
- // Disregard all APIs that have a manual model.
67
- not hasManualModel ( api )
76
+ private Callable liftedImpl ( Callable api ) {
77
+ (
78
+ result = getARelevantOverrideeOrImplementee ( api )
79
+ or
80
+ result = api and relevant ( api )
81
+ ) and
82
+ not exists ( getARelevantOverrideeOrImplementee ( result ) )
83
+ }
84
+
85
+ private predicate hasManualModel ( Callable api ) {
86
+ api = any ( FlowSummaryImpl:: Public:: SummarizedCallable sc | sc .applyManualModel ( ) ) or
87
+ api = any ( FlowSummaryImpl:: Public:: NeutralSummaryCallable sc | sc .hasManualModel ( ) )
68
88
}
69
89
70
90
/**
@@ -82,19 +102,37 @@ predicate isUninterestingForDataFlowModels(CS::Callable api) { isHigherOrder(api
82
102
predicate isUninterestingForTypeBasedFlowModels ( CS:: Callable api ) { none ( ) }
83
103
84
104
/**
85
- * A class of callables that are relevant generating summary, source and sinks models for.
105
+ * A class of callables that are potentially relevant for generating summary, source, sink
106
+ * and neutral models.
86
107
*
87
- * In the Standard library and 3rd party libraries it the callables that can be called
88
- * from outside the library itself.
108
+ * In the Standard library and 3rd party libraries it is the callables (or callables that have a
109
+ * super implementation) that can be called from outside the library itself.
89
110
*/
90
- class TargetApiSpecific extends CS:: Callable {
91
- TargetApiSpecific ( ) { isRelevantForModels ( this ) }
111
+ class TargetApiSpecific extends Callable {
112
+ private Callable lift ;
113
+
114
+ TargetApiSpecific ( ) {
115
+ lift = liftedImpl ( this ) and
116
+ not hasManualModel ( lift )
117
+ }
118
+
119
+ /**
120
+ * Gets the callable that a model will be lifted to.
121
+ *
122
+ * The lifted callable is relevant in terms of model
123
+ * generation (this is ensured by `liftedImpl`).
124
+ */
125
+ Callable lift ( ) { result = lift }
126
+
127
+ /**
128
+ * Holds if `this` is relevant in terms of model generation.
129
+ */
130
+ predicate isRelevant ( ) { relevant ( this ) }
92
131
}
93
132
94
- predicate asPartialModel = ExternalFlow:: asPartialModel / 1 ;
133
+ string asPartialModel ( TargetApiSpecific api ) { result = ExternalFlow:: asPartialModel ( api . lift ( ) ) }
95
134
96
- /** Computes the first 4 columns for neutral CSV rows of `c`. */
97
- predicate asPartialNeutralModel = ExternalFlow:: getSignature / 1 ;
135
+ string asPartialNeutralModel ( TargetApiSpecific api ) { result = ExternalFlow:: getSignature ( api ) }
98
136
99
137
/**
100
138
* Holds if `t` is a type that is generally used for bulk data in collection types.
@@ -193,7 +231,8 @@ predicate sinkModelSanitizer(DataFlow::Node node) { none() }
193
231
*/
194
232
predicate apiSource ( DataFlow:: Node source ) {
195
233
( isRelevantMemberAccess ( source ) or source instanceof DataFlow:: ParameterNode ) and
196
- isRelevantForModels ( source .getEnclosingCallable ( ) )
234
+ relevant ( source .getEnclosingCallable ( ) ) and
235
+ not hasManualModel ( source .getEnclosingCallable ( ) )
197
236
}
198
237
199
238
/**
0 commit comments