28
28
* types can be short names or fully qualified names (mixing these two options
29
29
* is not allowed within a single signature).
30
30
* 6. The `ext` column specifies additional API-graph-like edges. Currently
31
- * there are only two valid values: "" and "Attribute". The empty string has no
32
- * effect. "Attribute" applies if `name` and `signature` were left blank and
33
- * acts by selecting an element that is attributed with the attribute type
34
- * selected by the first 4 columns. This can be another member such as a field,
35
- * property, method, or parameter.
31
+ * there are only a few valid values: "", "Attribute", "Attribute.Getter" and "Attribute.Setter".
32
+ * The empty string has no effect. "Attribute" applies if `name` and `signature` were left blank
33
+ * and acts by selecting an element (except for properties and indexers) that is attributed with
34
+ * the attribute type selected by the first 4 columns. This can be another member such as
35
+ * a field, method, or parameter. "Attribute.Getter" and "Attribute.Setter" work similar to
36
+ * "Attribute", except that they can only be applied to properties and indexers.
37
+ * "Attribute.Setter" selects the setter element of a property/indexer and "Attribute.Getter"
38
+ * selects the getter.
36
39
* 7. The `input` column specifies how data enters the element selected by the
37
40
* first 6 columns, and the `output` column specifies how data leaves the
38
41
* element selected by the first 6 columns. For sinks, an `input` can be either "",
@@ -96,6 +99,7 @@ private import FlowSummaryImpl::Private::External
96
99
private import semmle.code.csharp.commons.QualifiedName
97
100
private import semmle.code.csharp.dispatch.OverridableCallable
98
101
private import semmle.code.csharp.frameworks.System
102
+ private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
99
103
private import codeql.mad.ModelValidation as SharedModelVal
100
104
101
105
/**
@@ -194,8 +198,6 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
194
198
195
199
/** Provides a query predicate to check the MaD models for validation errors. */
196
200
module ModelValidation {
197
- private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
198
-
199
201
private predicate getRelevantAccessPath ( string path ) {
200
202
summaryModel ( _, _, _, _, _, _, path , _, _, _, _) or
201
203
summaryModel ( _, _, _, _, _, _, _, path , _, _, _) or
@@ -289,7 +291,7 @@ module ModelValidation {
289
291
not signature .regexpMatch ( "|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)" ) and
290
292
result = "Dubious signature \"" + signature + "\" in " + pred + " model."
291
293
or
292
- not ext . regexpMatch ( "| Attribute" ) and
294
+ not ext = [ "" , "Attribute" , "Attribute.Getter" , " Attribute.Setter" ] and
293
295
result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
294
296
or
295
297
invalidProvenance ( provenance ) and
@@ -406,6 +408,30 @@ Declaration interpretBaseDeclaration(string namespace, string type, string name,
406
408
)
407
409
}
408
410
411
+ pragma [ inline]
412
+ private Declaration interpretExt ( Declaration d , ExtPath ext ) {
413
+ ext = "" and result = d
414
+ or
415
+ ext .getToken ( 0 ) = "Attribute" and
416
+ (
417
+ not exists ( ext .getToken ( 1 ) ) and
418
+ result .( Attributable ) .getAnAttribute ( ) .getType ( ) = d and
419
+ not result instanceof Property and
420
+ not result instanceof Indexer
421
+ or
422
+ exists ( string accessor | accessor = ext .getToken ( 1 ) |
423
+ result .( Accessor ) .getDeclaration ( ) .getAnAttribute ( ) .getType ( ) = d and
424
+ (
425
+ result instanceof Getter and
426
+ accessor = "Getter"
427
+ or
428
+ result instanceof Setter and
429
+ accessor = "Setter"
430
+ )
431
+ )
432
+ )
433
+ }
434
+
409
435
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
410
436
pragma [ nomagic]
411
437
Declaration interpretElement (
@@ -425,12 +451,18 @@ Declaration interpretElement(
425
451
)
426
452
)
427
453
|
428
- ext = "" and result = d
429
- or
430
- ext = "Attribute" and result .( Attributable ) .getAnAttribute ( ) .getType ( ) = d
454
+ result = interpretExt ( d , ext )
431
455
)
432
456
}
433
457
458
+ private predicate relevantExt ( string ext ) {
459
+ summaryModel ( _, _, _, _, _, ext , _, _, _, _, _) or
460
+ sourceModel ( _, _, _, _, _, ext , _, _, _, _) or
461
+ sinkModel ( _, _, _, _, _, ext , _, _, _, _)
462
+ }
463
+
464
+ private class ExtPath = AccessPathSyntax:: AccessPath< relevantExt / 1 > :: AccessPath ;
465
+
434
466
private predicate parseSynthField ( AccessPathToken c , string name ) {
435
467
c .getName ( ) = "SyntheticField" and name = c .getAnArgument ( )
436
468
}
0 commit comments