3
3
*/
4
4
5
5
import javascript
6
+ import semmle.javascript.Promises
6
7
7
8
module NoSQL {
8
9
/** An expression that is interpreted as a NoSQL query. */
@@ -65,6 +66,10 @@ private module MongoDB {
65
66
66
67
override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
67
68
69
+ override DataFlow:: Node getAResult ( ) {
70
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
71
+ }
72
+
68
73
DataFlow:: Node getACodeOperator ( ) {
69
74
result = getADollarWhereProperty ( this .getParameter ( queryArgIdx ) )
70
75
}
@@ -537,12 +542,29 @@ private module Mongoose {
537
542
// NB: the complete information is not easily accessible for deeply chained calls
538
543
f .getQueryArgument ( ) .getARhs ( ) = result
539
544
}
545
+
546
+ override DataFlow:: Node getAResult ( ) {
547
+ result = this .getCallback ( this .getNumArgument ( ) - 1 ) .getParameter ( 1 )
548
+ }
540
549
}
541
550
542
- class ExplicitQueryEvaluation extends DatabaseAccess {
551
+ class ExplicitQueryEvaluation extends DatabaseAccess , DataFlow:: CallNode {
552
+ string member ;
553
+
543
554
ExplicitQueryEvaluation ( ) {
544
555
// 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 ( ) )
546
568
}
547
569
548
570
override DataFlow:: Node getAQueryArgument ( ) {
@@ -588,6 +610,10 @@ private module Minimongo {
588
610
589
611
override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
590
612
613
+ override DataFlow:: Node getAResult ( ) {
614
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
615
+ }
616
+
591
617
DataFlow:: Node getACodeOperator ( ) {
592
618
result = getADollarWhereProperty ( this .getParameter ( queryArgIdx ) )
593
619
}
@@ -609,7 +635,7 @@ private module Minimongo {
609
635
* Provides classes modeling the MarsDB library.
610
636
*/
611
637
private module MarsDB {
612
- private class MarsDBAccess extends DatabaseAccess {
638
+ private class MarsDBAccess extends DatabaseAccess , DataFlow :: CallNode {
613
639
string method ;
614
640
615
641
MarsDBAccess ( ) {
@@ -623,21 +649,29 @@ private module MarsDB {
623
649
624
650
string getMethod ( ) { result = method }
625
651
652
+ override DataFlow:: Node getAResult ( ) {
653
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
654
+ }
655
+
626
656
override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
627
657
}
628
658
629
659
/** A call to a MarsDB query method. */
630
- private class QueryCall extends DatabaseAccess , API:: CallNode {
660
+ private class QueryCall extends MarsDBAccess , API:: CallNode {
631
661
int queryArgIdx ;
632
662
633
663
QueryCall ( ) {
634
664
exists ( string m |
635
- this .( MarsDBAccess ) . getMethod ( ) = m and
665
+ this .getMethod ( ) = m and
636
666
// implements parts of the Minimongo interface
637
667
Minimongo:: CollectionMethodSignatures:: interpretsArgumentAsQuery ( m , queryArgIdx )
638
668
)
639
669
}
640
670
671
+ override DataFlow:: Node getAResult ( ) {
672
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
673
+ }
674
+
641
675
override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( queryArgIdx ) }
642
676
643
677
DataFlow:: Node getACodeOperator ( ) {
@@ -744,9 +778,13 @@ private module Redis {
744
778
/**
745
779
* An access to a database through redis
746
780
*/
747
- class RedisDatabaseAccess extends DatabaseAccess {
781
+ class RedisDatabaseAccess extends DatabaseAccess , DataFlow :: CallNode {
748
782
RedisDatabaseAccess ( ) { this = redis ( ) .getMember ( _) .getACall ( ) }
749
783
784
+ override DataFlow:: Node getAResult ( ) {
785
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
786
+ }
787
+
750
788
override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
751
789
}
752
790
}
@@ -768,9 +806,13 @@ private module IoRedis {
768
806
/**
769
807
* An access to a database through ioredis
770
808
*/
771
- class IoRedisDatabaseAccess extends DatabaseAccess {
809
+ class IoRedisDatabaseAccess extends DatabaseAccess , DataFlow :: CallNode {
772
810
IoRedisDatabaseAccess ( ) { this = ioredis ( ) .getMember ( _) .getACall ( ) }
773
811
812
+ override DataFlow:: Node getAResult ( ) {
813
+ PromiseFlow:: loadStep ( this .getALocalUse ( ) , result , Promises:: valueProp ( ) )
814
+ }
815
+
774
816
override DataFlow:: Node getAQueryArgument ( ) { none ( ) }
775
817
}
776
818
}
0 commit comments