@@ -262,8 +262,13 @@ class GraphqlFieldDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCal
262262 /**
263263 * Gets an argument call inside this field definition.
264264 */
265- GraphqlFieldArgumentDefinitionMethodCall getAnArgumentCall ( ) {
266- result .getEnclosingCallable ( ) = this .getBlock ( )
265+ GraphqlFieldArgumentDefinitionMethodCall getAnArgumentCall ( ) { result = this .getArgumentCall ( _) }
266+
267+ /**
268+ * Gets the argument call for `name` inside this field definition.
269+ */
270+ GraphqlFieldArgumentDefinitionMethodCall getArgumentCall ( string name ) {
271+ result .getEnclosingCallable ( ) = this .getBlock ( ) and result .getArgumentName ( ) = name
267272 }
268273}
269274
@@ -277,7 +282,7 @@ class GraphqlInputObjectArgumentDefinitionCall extends DataFlow::CallNode {
277282 .getMember ( "InputObject" )
278283 .getADescendentModule ( )
279284 .getAnOwnModuleSelf ( )
280- .getAMethodCall ( )
285+ .getAMethodCall ( "argument" )
281286 }
282287
283288 /** Gets the name of the argument (i.e. the first argument to this `argument` method call) */
@@ -443,13 +448,16 @@ class GraphqlFieldResolutionMethod extends Method, Http::Server::RequestHandler:
443448
444449 /** Gets the method call which is the definition of the field corresponding to this resolver method. */
445450 GraphqlFieldDefinitionMethodCall getDefinition ( ) {
446- result
447- .getKeywordArgument ( "resolver_method" )
448- .getConstantValue ( )
449- .isStringlikeValue ( this .getName ( ) )
450- or
451- not exists ( result .getKeywordArgument ( "resolver_method" ) .( SymbolLiteral ) ) and
452- result .getFieldName ( ) = this .getName ( )
451+ result .getEnclosingModule ( ) = this .getEnclosingModule ( ) and
452+ (
453+ result
454+ .getKeywordArgument ( "resolver_method" )
455+ .getConstantValue ( )
456+ .isStringlikeValue ( this .getName ( ) )
457+ or
458+ not exists ( result .getKeywordArgument ( "resolver_method" ) .( SymbolLiteral ) ) and
459+ result .getFieldName ( ) = this .getName ( )
460+ )
453461 }
454462
455463 // check for a named argument the same name as a defined argument for this field
@@ -471,42 +479,78 @@ class GraphqlFieldResolutionMethod extends Method, Http::Server::RequestHandler:
471479 GraphqlSchemaObjectClass getGraphqlClass ( ) { result = schemaObjectClass }
472480}
473481
474- private DataFlow:: CallNode hashAccess ( DataFlow:: Node recv , string key ) {
475- result .asExpr ( ) instanceof ExprNodes:: ElementReferenceCfgNode and
476- result .getArgument ( 0 ) .getConstantValue ( ) .isStringlikeValue ( key ) and
477- result .getReceiver ( ) = recv
478- }
479-
480- private DataFlow:: CallNode parameterAccess (
482+ private DataFlow:: CallNode hashParameterAccess (
481483 GraphqlFieldResolutionMethod method , HashSplatParameter param , GraphqlType type
482484) {
483- exists ( GraphqlFieldArgumentDefinitionMethodCall def , string key |
485+ exists (
486+ DataFlow:: LocalSourceNode paramNode , GraphqlFieldArgumentDefinitionMethodCall def , string key
487+ |
484488 param = method .getAParameter ( ) and
489+ paramNode .( DataFlow:: ParameterNode ) .getParameter ( ) = param and
485490 def = method .getDefinition ( ) .getAnArgumentCall ( ) and
486491 (
487492 // Direct access to the params hash
488493 [ def .getArgumentType ( ) , def .getArgumentElementType ( ) ] = type and
489494 def .getArgumentName ( ) = key and
490- exists ( DataFlow:: Node paramRead |
491- paramRead .asExpr ( ) .getExpr ( ) = param .getVariable ( ) .getAnAccess ( ) .( VariableReadAccess ) and
492- result = hashAccess ( paramRead , key )
493- )
495+ paramNode .flowsTo ( hashAccess ( result , key ) )
494496 or
495497 // Nested access
496498 exists ( GraphqlType type2 |
497- parameterAccess ( method , param , type2 )
499+ hashParameterAccess ( method , param , type2 )
498500 .( DataFlow:: LocalSourceNode )
499- .flowsTo ( result .getReceiver ( ) ) and
500- result = hashAccess ( _, key ) and
501+ .flowsTo ( hashAccess ( result , key ) ) and
501502 type2 .getFieldOrArgument ( key ) = type
502503 )
503504 )
504505 )
505506}
506507
508+ private DataFlow:: Node parameterAccess (
509+ GraphqlFieldResolutionMethod method , DataFlow:: LocalSourceNode param , GraphqlType type
510+ ) {
511+ param = getAGraphqlParameter ( method , type ) and
512+ result = param
513+ or
514+ exists ( string key , GraphqlType type2 |
515+ param = parameterAccess ( method , _, type2 ) and
516+ param .flowsTo ( hashAccess ( result , key ) ) and
517+ type2 .getFieldOrArgument ( key ) = type
518+ )
519+ }
520+
521+ private DataFlow:: ParameterNode getAGraphqlParameter (
522+ GraphqlFieldResolutionMethod method , GraphqlType type
523+ ) {
524+ result .getCallable ( ) = method and
525+ (
526+ result .getParameter ( ) instanceof KeywordParameter and
527+ exists ( GraphqlFieldArgumentDefinitionMethodCall c |
528+ c = method .getDefinition ( ) .getArgumentCall ( result .getName ( ) )
529+ |
530+ type = [ c .getArgumentType ( ) , c .getArgumentElementType ( ) ]
531+ )
532+ or
533+ result .getParameter ( ) instanceof SimpleParameter and
534+ type = method .getDefinition ( ) .getFieldType ( )
535+ )
536+ }
537+
538+ /**
539+ * Gets the receiver of the hash access `access` with key `key`.
540+ * For example, in `h["foo"]` the receiver is `h`, the key is "foo"
541+ * and `access` is the dataflow node for the whole expression.
542+ */
543+ private DataFlow:: Node hashAccess ( DataFlow:: CallNode access , string key ) {
544+ access .asExpr ( ) instanceof ExprNodes:: ElementReferenceCfgNode and
545+ access .getArgument ( 0 ) .getConstantValue ( ) .isStringlikeValue ( key ) and
546+ access .getReceiver ( ) = result
547+ }
548+
507549private class GraphqlParameterAccess extends RemoteFlowSource:: Range {
508550 GraphqlParameterAccess ( ) {
509- exists ( GraphqlType type | this = parameterAccess ( _, _, type ) and type .isScalar ( ) )
551+ exists ( GraphqlType type | type .isScalar ( ) |
552+ this = hashParameterAccess ( _, _, type ) or this = parameterAccess ( _, _, type )
553+ )
510554 }
511555
512556 override string getSourceType ( ) { result = "GraphQL" }
0 commit comments