@@ -390,7 +390,7 @@ module Express {
390390 }
391391
392392 /** An Express response source. */
393- abstract private class ResponseSource extends HTTP:: Servers:: ResponseSource { }
393+ abstract class ResponseSource extends HTTP:: Servers:: ResponseSource { }
394394
395395 /**
396396 * An Express response source, that is, the response parameter of a
@@ -421,7 +421,7 @@ module Express {
421421 }
422422
423423 /** An Express request source. */
424- abstract private class RequestSource extends HTTP:: Servers:: RequestSource { }
424+ abstract class RequestSource extends HTTP:: Servers:: RequestSource { }
425425
426426 /**
427427 * An Express request source, that is, the request parameter of a
@@ -465,73 +465,98 @@ module Express {
465465 * Gets a reference to the "query" object from a request-object originating from route-handler `rh`.
466466 */
467467 DataFlow:: SourceNode getAQueryObjectReference ( DataFlow:: TypeTracker t , RouteHandler rh ) {
468- t .startInProp ( "query" ) and
469- result = rh .getARequestSource ( )
470- or
471- exists ( DataFlow:: TypeTracker t2 | result = getAQueryObjectReference ( t2 , rh ) .track ( t2 , t ) )
468+ result = queryRef ( rh .getARequestSource ( ) , t )
472469 }
473470
474471 /**
475472 * Gets a reference to the "params" object from a request-object originating from route-handler `rh`.
476473 */
477474 DataFlow:: SourceNode getAParamsObjectReference ( DataFlow:: TypeTracker t , RouteHandler rh ) {
478- t .startInProp ( "params" ) and
479- result = rh .getARequestSource ( )
475+ result = paramsRef ( rh .getARequestSource ( ) , t )
476+ }
477+
478+ /** The input parameter to an `app.param()` route handler. */
479+ private class ParamHandlerInputAccess extends HTTP:: RequestInputAccess {
480+ RouteHandler rh ;
481+
482+ ParamHandlerInputAccess ( ) {
483+ exists ( RouteSetup setup | rh = setup .getARouteHandler ( ) |
484+ this = DataFlow:: parameterNode ( rh .getRouteHandlerParameter ( "parameter" ) )
485+ )
486+ }
487+
488+ override HTTP:: RouteHandler getRouteHandler ( ) { result = rh }
489+
490+ override string getKind ( ) { result = "parameter" }
491+ }
492+
493+ /** Gets a data flow node referring to `req.query`. */
494+ private DataFlow:: SourceNode queryRef ( RequestSource req , DataFlow:: TypeTracker t ) {
495+ t .start ( ) and
496+ result = req .ref ( ) .getAPropertyRead ( "query" )
497+ or
498+ exists ( DataFlow:: TypeTracker t2 | result = queryRef ( req , t2 ) .track ( t2 , t ) )
499+ }
500+
501+ /** Gets a data flow node referring to `req.query`. */
502+ private DataFlow:: SourceNode queryRef ( RequestSource req ) {
503+ result = queryRef ( req , DataFlow:: TypeTracker:: end ( ) )
504+ }
505+
506+ /** Gets a data flow node referring to `req.params`. */
507+ private DataFlow:: SourceNode paramsRef ( RequestSource req , DataFlow:: TypeTracker t ) {
508+ t .start ( ) and
509+ result = req .ref ( ) .getAPropertyRead ( "params" )
480510 or
481- exists ( DataFlow:: TypeTracker t2 | result = getAParamsObjectReference ( t2 , rh ) .track ( t2 , t ) )
511+ exists ( DataFlow:: TypeTracker t2 | result = paramsRef ( req , t2 ) .track ( t2 , t ) )
512+ }
513+
514+ /** Gets a data flow node referring to `req.params`. */
515+ private DataFlow:: SourceNode paramsRef ( RequestSource req ) {
516+ result = paramsRef ( req , DataFlow:: TypeTracker:: end ( ) )
482517 }
483518
484519 /**
485520 * An access to a user-controlled Express request input.
486521 */
487522 class RequestInputAccess extends HTTP:: RequestInputAccess {
488- RouteHandler rh ;
523+ RequestSource request ;
489524 string kind ;
490525
491526 RequestInputAccess ( ) {
492527 kind = "parameter" and
493- this =
494- [
495- getAQueryObjectReference ( DataFlow:: TypeTracker:: end ( ) , rh ) ,
496- getAParamsObjectReference ( DataFlow:: TypeTracker:: end ( ) , rh )
497- ] .getAPropertyRead ( )
528+ this = [ queryRef ( request ) , paramsRef ( request ) ] .getAPropertyRead ( )
498529 or
499- exists ( DataFlow:: SourceNode request | request = rh . getARequestSource ( ) .ref ( ) |
530+ exists ( DataFlow:: SourceNode ref | ref = request .ref ( ) |
500531 kind = "parameter" and
501- this = request .getAMethodCall ( "param" )
532+ this = ref .getAMethodCall ( "param" )
502533 or
503534 // `req.originalUrl`
504535 kind = "url" and
505- this = request .getAPropertyRead ( "originalUrl" )
536+ this = ref .getAPropertyRead ( "originalUrl" )
506537 or
507538 // `req.cookies`
508539 kind = "cookie" and
509- this = request .getAPropertyRead ( "cookies" )
540+ this = ref .getAPropertyRead ( "cookies" )
510541 or
511542 // `req.files`, treated the same as `req.body`.
512543 // `express-fileupload` uses .files, and `multer` uses .files or .file
513544 kind = "body" and
514- this = request .getAPropertyRead ( [ "files" , "file" ] )
515- )
516- or
517- kind = "body" and
518- this .asExpr ( ) = rh .getARequestBodyAccess ( )
519- or
520- // `value` in `router.param('foo', (req, res, next, value) => { ... })`
521- kind = "parameter" and
522- exists ( RouteSetup setup | rh = setup .getARouteHandler ( ) |
523- this = DataFlow:: parameterNode ( rh .getRouteHandlerParameter ( "parameter" ) )
545+ this = ref .getAPropertyRead ( [ "files" , "file" ] )
546+ or
547+ kind = "body" and
548+ this = ref .getAPropertyRead ( "body" )
524549 )
525550 }
526551
527- override RouteHandler getRouteHandler ( ) { result = rh }
552+ override RouteHandler getRouteHandler ( ) { result = request . getRouteHandler ( ) }
528553
529554 override string getKind ( ) { result = kind }
530555
531556 override predicate isUserControlledObject ( ) {
532557 kind = "body" and
533558 exists ( ExpressLibraries:: BodyParser bodyParser , RouteHandlerExpr expr |
534- expr .getBody ( ) = rh and
559+ expr .getBody ( ) = request . getRouteHandler ( ) and
535560 bodyParser .producesUserControlledObjects ( ) and
536561 bodyParser .flowsToExpr ( expr .getAMatchingAncestor ( ) )
537562 )
@@ -542,43 +567,26 @@ module Express {
542567 forall ( ExpressLibraries:: BodyParser bodyParser | bodyParser .producesUserControlledObjects ( ) )
543568 or
544569 kind = "parameter" and
545- exists ( DataFlow:: Node request | request = DataFlow:: valueNode ( rh .getARequestExpr ( ) ) |
546- this .( DataFlow:: MethodCallNode ) .calls ( request , "param" )
547- )
570+ this = request .ref ( ) .getAMethodCall ( "param" )
548571 or
549572 // `req.query.name`
550573 kind = "parameter" and
551- this = getAQueryObjectReference ( DataFlow :: TypeTracker :: end ( ) , rh ) .getAPropertyRead ( )
574+ this = queryRef ( request ) .getAPropertyRead ( )
552575 }
553576 }
554577
555578 /**
556579 * An access to a header on an Express request.
557580 */
558581 private class RequestHeaderAccess extends HTTP:: RequestHeaderAccess {
559- RouteHandler rh ;
582+ RequestSource request ;
560583
561584 RequestHeaderAccess ( ) {
562- exists ( DataFlow:: Node request | request = DataFlow:: valueNode ( rh .getARequestExpr ( ) ) |
563- exists ( string methodName |
564- // `req.get(...)` or `req.header(...)`
565- this .( DataFlow:: MethodCallNode ) .calls ( request , methodName )
566- |
567- methodName = "get" or
568- methodName = "header"
569- )
570- or
571- exists ( DataFlow:: PropRead headers |
572- // `req.headers.name`
573- headers .accesses ( request , "headers" ) and
574- this = headers .getAPropertyRead ( )
575- )
576- or
577- exists ( string propName | propName = "host" or propName = "hostname" |
578- // `req.host` and `req.hostname` are derived from headers
579- this .( DataFlow:: PropRead ) .accesses ( request , propName )
580- )
581- )
585+ this = request .ref ( ) .getAMethodCall ( [ "get" , "header" ] )
586+ or
587+ this = request .ref ( ) .getAPropertyRead ( "headers" ) .getAPropertyRead ( )
588+ or
589+ this = request .ref ( ) .getAPropertyRead ( [ "host" , "hostname" ] )
582590 }
583591
584592 override string getAHeaderName ( ) {
@@ -591,22 +599,15 @@ module Express {
591599 )
592600 }
593601
594- override RouteHandler getRouteHandler ( ) { result = rh }
602+ override RouteHandler getRouteHandler ( ) { result = request . getRouteHandler ( ) }
595603
596604 override string getKind ( ) { result = "header" }
597605 }
598606
599607 /**
600608 * HTTP headers created by Express calls
601609 */
602- abstract private class ExplicitHeader extends HTTP:: ExplicitHeaderDefinition {
603- Expr response ;
604-
605- /**
606- * Gets the response expression that this header is set on.
607- */
608- Expr getResponse ( ) { result = response }
609- }
610+ abstract private class ExplicitHeader extends HTTP:: ExplicitHeaderDefinition { }
610611
611612 /**
612613 * Holds if `e` is an HTTP request object.
@@ -635,16 +636,13 @@ module Express {
635636 * An invocation of the `redirect` method of an HTTP response object.
636637 */
637638 private class RedirectInvocation extends HTTP:: RedirectInvocation , MethodCallExpr {
638- RouteHandler rh ;
639+ ResponseSource response ;
639640
640- RedirectInvocation ( ) {
641- getReceiver ( ) = rh .getAResponseExpr ( ) and
642- getMethodName ( ) = "redirect"
643- }
641+ RedirectInvocation ( ) { this = response .ref ( ) .getAMethodCall ( "redirect" ) .asExpr ( ) }
644642
645643 override Expr getUrlArgument ( ) { result = getLastArgument ( ) }
646644
647- override RouteHandler getRouteHandler ( ) { result = rh }
645+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
648646 }
649647
650648 /**
@@ -662,21 +660,18 @@ module Express {
662660 * An invocation of the `set` or `header` method on an HTTP response object that
663661 * sets multiple headers.
664662 */
665- class SetMultipleHeaders extends ExplicitHeader , DataFlow:: ValueNode {
666- override MethodCallExpr astNode ;
667- RouteHandler rh ;
663+ class SetMultipleHeaders extends ExplicitHeader , DataFlow:: MethodCallNode {
664+ ResponseSource response ;
668665
669666 SetMultipleHeaders ( ) {
670- astNode .getReceiver ( ) = rh .getAResponseExpr ( ) and
671- response = astNode .getReceiver ( ) and
672- astNode .getMethodName ( ) = any ( string n | n = "set" or n = "header" ) and
673- astNode .getNumArgument ( ) = 1
667+ this = response .ref ( ) .getAMethodCall ( [ "set" , "header" ] ) and
668+ getNumArgument ( ) = 1
674669 }
675670
676671 /**
677672 * Gets a reference to the multiple headers object that is to be set.
678673 */
679- private DataFlow:: SourceNode getAHeaderSource ( ) { result .flowsToExpr ( astNode . getArgument ( 0 ) ) }
674+ private DataFlow:: SourceNode getAHeaderSource ( ) { result .flowsTo ( getArgument ( 0 ) ) }
680675
681676 override predicate definesExplicitly ( string headerName , Expr headerValue ) {
682677 exists ( string header |
@@ -685,7 +680,7 @@ module Express {
685680 )
686681 }
687682
688- override RouteHandler getRouteHandler ( ) { result = rh }
683+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
689684
690685 override Expr getNameExpr ( ) {
691686 exists ( DataFlow:: PropWrite write | getAHeaderSource ( ) .getAPropertyWrite ( ) = write |
@@ -705,31 +700,26 @@ module Express {
705700 * An argument passed to the `send` or `end` method of an HTTP response object.
706701 */
707702 private class ResponseSendArgument extends HTTP:: ResponseSendArgument {
708- RouteHandler rh ;
703+ ResponseSource response ;
709704
710- ResponseSendArgument ( ) {
711- exists ( MethodCallExpr mce |
712- mce .calls ( rh .getAResponseExpr ( ) , "send" ) and
713- this = mce .getArgument ( 0 )
714- )
715- }
705+ ResponseSendArgument ( ) { this = response .ref ( ) .getAMethodCall ( "send" ) .getArgument ( 0 ) .asExpr ( ) }
716706
717- override RouteHandler getRouteHandler ( ) { result = rh }
707+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
718708 }
719709
720710 /**
721711 * An invocation of the `cookie` method on an HTTP response object.
722712 */
723713 class SetCookie extends HTTP:: CookieDefinition , MethodCallExpr {
724- RouteHandler rh ;
714+ ResponseSource response ;
725715
726- SetCookie ( ) { calls ( rh . getAResponseExpr ( ) , "cookie" ) }
716+ SetCookie ( ) { this = response . ref ( ) . getAMethodCall ( "cookie" ) . asExpr ( ) }
727717
728718 override Expr getNameArgument ( ) { result = getArgument ( 0 ) }
729719
730720 override Expr getValueArgument ( ) { result = getArgument ( 1 ) }
731721
732- override RouteHandler getRouteHandler ( ) { result = rh }
722+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
733723 }
734724
735725 /**
@@ -750,19 +740,19 @@ module Express {
750740 * An object passed to the `render` method of an HTTP response object.
751741 */
752742 class TemplateObjectInput extends DataFlow:: Node {
753- RouteHandler rh ;
743+ ResponseSource response ;
754744
755745 TemplateObjectInput ( ) {
756746 exists ( DataFlow:: MethodCallNode render |
757- render . calls ( rh . getAResponseExpr ( ) . flow ( ) , "render" ) and
747+ render = response . ref ( ) . getAMethodCall ( "render" ) and
758748 this = render .getArgument ( 1 )
759749 )
760750 }
761751
762752 /**
763753 * Gets the route handler that uses this object.
764754 */
765- RouteHandler getRouteHandler ( ) { result = rh }
755+ RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
766756 }
767757
768758 /**
0 commit comments