33 */
44
55import javascript
6+ import semmle.javascript.Promises
67
78module NoSQL {
89 /** An expression that is interpreted as a NoSQL query. */
@@ -65,6 +66,10 @@ private module MongoDB {
6566
6667 override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
6768
69+ override DataFlow:: Node getAResult ( ) {
70+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
71+ }
72+
6873 DataFlow:: Node getACodeOperator ( ) {
6974 result = getADollarWhereProperty ( this .getParameter ( queryArgIdx ) )
7075 }
@@ -537,12 +542,29 @@ private module Mongoose {
537542 // NB: the complete information is not easily accessible for deeply chained calls
538543 f .getQueryArgument ( ) .getARhs ( ) = result
539544 }
545+
546+ override DataFlow:: Node getAResult ( ) {
547+ result = this .getCallback ( this .getNumArgument ( ) - 1 ) .getParameter ( 1 )
548+ }
540549 }
541550
542- class ExplicitQueryEvaluation extends DatabaseAccess {
551+ class ExplicitQueryEvaluation extends DatabaseAccess , DataFlow:: CallNode {
552+ string member ;
553+
543554 ExplicitQueryEvaluation ( ) {
544555 // explicit execution using a Query method call
545- Query:: getAMongooseQuery ( ) .getMember ( [ "exec" , "then" , "catch" ] ) .getACall ( ) = this
556+ member = [ "exec" , "then" , "catch" ] and
557+ Query:: getAMongooseQuery ( ) .getMember ( member ) .getACall ( ) = this
558+ }
559+
560+ private int resultParamIndex ( ) {
561+ member = "then" and result = 0
562+ or
563+ member = "exec" and result = 1
564+ }
565+
566+ override DataFlow:: Node getAResult ( ) {
567+ result = this .getCallback ( _) .getParameter ( this .resultParamIndex ( ) )
546568 }
547569
548570 override DataFlow:: Node getAQueryArgument ( ) {
@@ -588,6 +610,10 @@ private module Minimongo {
588610
589611 override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
590612
613+ override DataFlow:: Node getAResult ( ) {
614+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
615+ }
616+
591617 DataFlow:: Node getACodeOperator ( ) {
592618 result = getADollarWhereProperty ( this .getParameter ( queryArgIdx ) )
593619 }
@@ -609,7 +635,7 @@ private module Minimongo {
609635 * Provides classes modeling the MarsDB library.
610636 */
611637private module MarsDB {
612- private class MarsDBAccess extends DatabaseAccess {
638+ private class MarsDBAccess extends DatabaseAccess , DataFlow :: CallNode {
613639 string method ;
614640
615641 MarsDBAccess ( ) {
@@ -623,21 +649,29 @@ private module MarsDB {
623649
624650 string getMethod ( ) { result = method }
625651
652+ override DataFlow:: Node getAResult ( ) {
653+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
654+ }
655+
626656 override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
627657 }
628658
629659 /** A call to a MarsDB query method. */
630- private class QueryCall extends DatabaseAccess , API:: CallNode {
660+ private class QueryCall extends MarsDBAccess , API:: CallNode {
631661 int queryArgIdx ;
632662
633663 QueryCall ( ) {
634664 exists ( string m |
635- this .( MarsDBAccess ) . getMethod ( ) = m and
665+ this .getMethod ( ) = m and
636666 // implements parts of the Minimongo interface
637667 Minimongo:: CollectionMethodSignatures:: interpretsArgumentAsQuery ( m , queryArgIdx )
638668 )
639669 }
640670
671+ override DataFlow:: Node getAResult ( ) {
672+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
673+ }
674+
641675 override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
642676
643677 DataFlow:: Node getACodeOperator ( ) {
@@ -744,9 +778,13 @@ private module Redis {
744778 /**
745779 * An access to a database through redis
746780 */
747- class RedisDatabaseAccess extends DatabaseAccess {
781+ class RedisDatabaseAccess extends DatabaseAccess , DataFlow :: CallNode {
748782 RedisDatabaseAccess ( ) { this = redis ( ) .getMember ( _) .getACall ( ) }
749783
784+ override DataFlow:: Node getAResult ( ) {
785+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
786+ }
787+
750788 override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
751789 }
752790}
@@ -768,9 +806,13 @@ private module IoRedis {
768806 /**
769807 * An access to a database through ioredis
770808 */
771- class IoRedisDatabaseAccess extends DatabaseAccess {
809+ class IoRedisDatabaseAccess extends DatabaseAccess , DataFlow :: CallNode {
772810 IoRedisDatabaseAccess ( ) { this = ioredis ( ) .getMember ( _) .getACall ( ) }
773811
812+ override DataFlow:: Node getAResult ( ) {
813+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
814+ }
815+
774816 override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
775817 }
776818}
0 commit comments