2828 * types can be short names or fully qualified names (mixing these two options
2929 * is not allowed within a single signature).
3030 * 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.
3639 * 7. The `input` column specifies how data enters the element selected by the
3740 * first 6 columns, and the `output` column specifies how data leaves the
3841 * element selected by the first 6 columns. For sinks, an `input` can be either "",
@@ -96,6 +99,7 @@ private import FlowSummaryImpl::Private::External
9699private import semmle.code.csharp.commons.QualifiedName
97100private import semmle.code.csharp.dispatch.OverridableCallable
98101private import semmle.code.csharp.frameworks.System
102+ private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
99103private import codeql.mad.ModelValidation as SharedModelVal
100104
101105/**
@@ -194,8 +198,6 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
194198
195199/** Provides a query predicate to check the MaD models for validation errors. */
196200module ModelValidation {
197- private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
198-
199201 private predicate getRelevantAccessPath ( string path ) {
200202 summaryModel ( _, _, _, _, _, _, path , _, _, _, _) or
201203 summaryModel ( _, _, _, _, _, _, _, path , _, _, _) or
@@ -289,7 +291,7 @@ module ModelValidation {
289291 not signature .regexpMatch ( "|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)" ) and
290292 result = "Dubious signature \"" + signature + "\" in " + pred + " model."
291293 or
292- not ext . regexpMatch ( "| Attribute" ) and
294+ not ext = [ "" , "Attribute" , "Attribute.Getter" , " Attribute.Setter" ] and
293295 result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
294296 or
295297 invalidProvenance ( provenance ) and
@@ -406,6 +408,30 @@ Declaration interpretBaseDeclaration(string namespace, string type, string name,
406408 )
407409}
408410
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+
409435/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
410436pragma [ nomagic]
411437Declaration interpretElement (
@@ -425,12 +451,18 @@ Declaration interpretElement(
425451 )
426452 )
427453 |
428- ext = "" and result = d
429- or
430- ext = "Attribute" and result .( Attributable ) .getAnAttribute ( ) .getType ( ) = d
454+ result = interpretExt ( d , ext )
431455 )
432456}
433457
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+
434466private predicate parseSynthField ( AccessPathToken c , string name ) {
435467 c .getName ( ) = "SyntheticField" and name = c .getAnArgument ( )
436468}
0 commit comments