@@ -96,6 +96,7 @@ private import FlowSummaryImpl::Private::External
9696private import semmle.code.csharp.commons.QualifiedName
9797private import semmle.code.csharp.dispatch.OverridableCallable
9898private import semmle.code.csharp.frameworks.System
99+ private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
99100private import codeql.mad.ModelValidation as SharedModelVal
100101
101102/**
@@ -194,8 +195,6 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
194195
195196/** Provides a query predicate to check the MaD models for validation errors. */
196197module ModelValidation {
197- private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
198-
199198 private predicate getRelevantAccessPath ( string path ) {
200199 summaryModel ( _, _, _, _, _, _, path , _, _, _, _) or
201200 summaryModel ( _, _, _, _, _, _, _, path , _, _, _) or
@@ -289,7 +288,7 @@ module ModelValidation {
289288 not signature .regexpMatch ( "|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)" ) and
290289 result = "Dubious signature \"" + signature + "\" in " + pred + " model."
291290 or
292- not ext . regexpMatch ( "| Attribute" ) and
291+ not ext = [ "" , "Attribute" , "Attribute.Getter" , " Attribute.Setter" ] and
293292 result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
294293 or
295294 invalidProvenance ( provenance ) and
@@ -406,6 +405,30 @@ Declaration interpretBaseDeclaration(string namespace, string type, string name,
406405 )
407406}
408407
408+ pragma [ inline]
409+ private Declaration interpretExt ( Declaration d , ExtPath ext ) {
410+ ext = "" and result = d
411+ or
412+ ext .getToken ( 0 ) = "Attribute" and
413+ (
414+ not exists ( ext .getToken ( 1 ) ) and
415+ result .( Attributable ) .getAnAttribute ( ) .getType ( ) = d and
416+ not result instanceof Property and
417+ not result instanceof Indexer
418+ or
419+ exists ( string accessor | accessor = ext .getToken ( 1 ) |
420+ result .( Accessor ) .getDeclaration ( ) .getAnAttribute ( ) .getType ( ) = d and
421+ (
422+ result instanceof Getter and
423+ accessor = "Getter"
424+ or
425+ result instanceof Setter and
426+ accessor = "Setter"
427+ )
428+ )
429+ )
430+ }
431+
409432/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
410433pragma [ nomagic]
411434Declaration interpretElement (
@@ -425,14 +448,18 @@ Declaration interpretElement(
425448 )
426449 )
427450 |
428- ext = "" and result = d
429- or
430- ext = "Attribute" and
431- result .( Attributable ) .getAnAttribute ( ) .getType ( ) = d and
432- not result instanceof Property
451+ result = interpretExt ( d , ext )
433452 )
434453}
435454
455+ private predicate relevantExt ( string ext ) {
456+ summaryModel ( _, _, _, _, _, ext , _, _, _, _, _) or
457+ sourceModel ( _, _, _, _, _, ext , _, _, _, _) or
458+ sinkModel ( _, _, _, _, _, ext , _, _, _, _)
459+ }
460+
461+ private class ExtPath = AccessPathSyntax:: AccessPath< relevantExt / 1 > :: AccessPath ;
462+
436463private predicate parseSynthField ( AccessPathToken c , string name ) {
437464 c .getName ( ) = "SyntheticField" and name = c .getAnArgument ( )
438465}
0 commit comments