@@ -4,6 +4,7 @@ private import DataFlowPrivate
44private import codeql.ruby.typetracking.TypeTracker
55private import codeql.ruby.ast.internal.Module
66private import FlowSummaryImpl as FlowSummaryImpl
7+ private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
78private import codeql.ruby.dataflow.FlowSummary
89
910newtype TReturnKind =
@@ -230,6 +231,30 @@ private module Cached {
230231 result = yieldCall ( call )
231232 )
232233 }
234+
235+ cached
236+ newtype TArgumentPosition =
237+ TSelfArgumentPosition ( ) or
238+ TBlockArgumentPosition ( ) or
239+ TPositionalArgumentPosition ( int pos ) {
240+ exists ( Call c | exists ( c .getArgument ( pos ) ) )
241+ or
242+ FlowSummaryImplSpecific:: ParsePositions:: isParsedParameterPosition ( _, pos )
243+ } or
244+ TKeywordArgumentPosition ( string name ) { name = any ( KeywordParameter kp ) .getName ( ) }
245+
246+ cached
247+ newtype TParameterPosition =
248+ TSelfParameterPosition ( ) or
249+ TBlockParameterPosition ( ) or
250+ TPositionalParameterPosition ( int pos ) {
251+ pos = any ( Parameter p ) .getPosition ( )
252+ or
253+ pos in [ 0 .. 10 ] // TODO: remove once `Argument[_]` summaries are replaced with `Argument[i..]`
254+ or
255+ FlowSummaryImplSpecific:: ParsePositions:: isParsedArgumentPosition ( _, pos )
256+ } or
257+ TKeywordParameterPosition ( string name ) { name = any ( KeywordParameter kp ) .getName ( ) }
233258}
234259
235260import Cached
@@ -458,18 +483,66 @@ predicate exprNodeReturnedFrom(DataFlow::ExprNode e, Callable c) {
458483 )
459484}
460485
461- private int parameterPosition ( ) { result in [ - 2 .. max ( [ any ( Parameter p ) .getPosition ( ) , 10 ] ) ] }
486+ /** A parameter position. */
487+ class ParameterPosition extends TParameterPosition {
488+ /** Holds if this position represents a `self` parameter. */
489+ predicate isSelf ( ) { this = TSelfParameterPosition ( ) }
462490
463- /** A parameter position represented by an integer. */
464- class ParameterPosition extends int {
465- ParameterPosition ( ) { this = parameterPosition ( ) }
491+ /** Holds if this position represents a block parameter. */
492+ predicate isBlock ( ) { this = TBlockParameterPosition ( ) }
493+
494+ /** Holds if this position represents a positional parameter at position `pos`. */
495+ predicate isPositional ( int pos ) { this = TPositionalParameterPosition ( pos ) }
496+
497+ /** Holds if this position represents a keyword parameter named `name`. */
498+ predicate isKeyword ( string name ) { this = TKeywordParameterPosition ( name ) }
499+
500+ /** Gets a textual representation of this position. */
501+ string toString ( ) {
502+ this .isSelf ( ) and result = "self"
503+ or
504+ this .isBlock ( ) and result = "block"
505+ or
506+ exists ( int pos | this .isPositional ( pos ) and result = "position " + pos )
507+ or
508+ exists ( string name | this .isKeyword ( name ) and result = "keyword " + name )
509+ }
466510}
467511
468- /** An argument position represented by an integer. */
469- class ArgumentPosition extends int {
470- ArgumentPosition ( ) { this = parameterPosition ( ) }
512+ /** An argument position. */
513+ class ArgumentPosition extends TArgumentPosition {
514+ /** Holds if this position represents a `self` argument. */
515+ predicate isSelf ( ) { this = TSelfArgumentPosition ( ) }
516+
517+ /** Holds if this position represents a block argument. */
518+ predicate isBlock ( ) { this = TBlockArgumentPosition ( ) }
519+
520+ /** Holds if this position represents a positional argument at position `pos`. */
521+ predicate isPositional ( int pos ) { this = TPositionalArgumentPosition ( pos ) }
522+
523+ /** Holds if this position represents a keyword argument named `name`. */
524+ predicate isKeyword ( string name ) { this = TKeywordArgumentPosition ( name ) }
525+
526+ /** Gets a textual representation of this position. */
527+ string toString ( ) {
528+ this .isSelf ( ) and result = "self"
529+ or
530+ this .isBlock ( ) and result = "block"
531+ or
532+ exists ( int pos | this .isPositional ( pos ) and result = "position " + pos )
533+ or
534+ exists ( string name | this .isKeyword ( name ) and result = "keyword " + name )
535+ }
471536}
472537
473538/** Holds if arguments at position `apos` match parameters at position `ppos`. */
474539pragma [ inline]
475- predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
540+ predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) {
541+ ppos .isSelf ( ) and apos .isSelf ( )
542+ or
543+ ppos .isBlock ( ) and apos .isBlock ( )
544+ or
545+ exists ( int pos | ppos .isPositional ( pos ) and apos .isPositional ( pos ) )
546+ or
547+ exists ( string name | ppos .isKeyword ( name ) and apos .isKeyword ( name ) )
548+ }
0 commit comments