@@ -8,6 +8,7 @@ private import semmle.code.csharp.commons.Collections as Collections
88private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
99private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010private import semmle.code.csharp.frameworks.system.linq.Expressions
11+ private import semmle.code.csharp.frameworks.System
1112import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
1213import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
1314import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
@@ -35,12 +36,23 @@ private predicate irrelevantAccessor(CS::Accessor a) {
3536}
3637
3738private 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
4456 // Disregard properties that have both a get and a set accessor,
4557 // which implicitly means auto implemented properties.
4658 irrelevantAccessor ( api )
@@ -53,18 +65,26 @@ private predicate relevant(Callable api) {
5365 not isUninterestingForModels ( api )
5466}
5567
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 )
5970}
6071
6172/**
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.
6375 */
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 ( ) )
6888}
6989
7090/**
@@ -82,19 +102,37 @@ predicate isUninterestingForDataFlowModels(CS::Callable api) { isHigherOrder(api
82102predicate isUninterestingForTypeBasedFlowModels ( CS:: Callable api ) { none ( ) }
83103
84104/**
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.
86107 *
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.
89110 */
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 ) }
92131}
93132
94- predicate asPartialModel = ExternalFlow:: asPartialModel / 1 ;
133+ string asPartialModel ( TargetApiSpecific api ) { result = ExternalFlow:: asPartialModel ( api . lift ( ) ) }
95134
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 ) }
98136
99137/**
100138 * 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() }
193231 */
194232predicate apiSource ( DataFlow:: Node source ) {
195233 ( isRelevantMemberAccess ( source ) or source instanceof DataFlow:: ParameterNode ) and
196- isRelevantForModels ( source .getEnclosingCallable ( ) )
234+ relevant ( source .getEnclosingCallable ( ) ) and
235+ not hasManualModel ( source .getEnclosingCallable ( ) )
197236}
198237
199238/**
0 commit comments