@@ -11,106 +11,100 @@ private import experimental.semmle.python.Concepts
11
11
private import semmle.python.ApiGraphs
12
12
13
13
private module NoSQL {
14
- /** Gets a reference to a `MongoClient` instance. */
15
- private API:: Node mongoClientInstance ( ) {
16
- result = API:: moduleImport ( "pymongo" ) .getMember ( "MongoClient" ) .getReturn ( ) or
17
- result =
18
- API:: moduleImport ( "flask_mongoengine" )
19
- .getMember ( "MongoEngine" )
20
- .getReturn ( )
21
- .getMember ( "get_db" )
22
- .getReturn ( ) or
23
- result =
24
- API:: moduleImport ( [ "mongoengine" , "mongoengine.connection" ] )
25
- .getMember ( [ "get_db" , "connect" ] )
26
- .getReturn ( ) or
14
+ /** API Nodes returning `Mongo` instances. */
15
+ private API:: Node pyMongo ( ) {
16
+ result = API:: moduleImport ( "pymongo" ) .getMember ( "MongoClient" ) .getReturn ( )
17
+ }
18
+
19
+ private API:: Node flask_PyMongo ( ) {
27
20
result = API:: moduleImport ( "flask_pymongo" ) .getMember ( "PyMongo" ) .getReturn ( )
28
21
}
29
22
30
- /** Gets a reference to a `MongoClient` DB. */
31
- private DataFlow:: LocalSourceNode mongoClientDB ( DataFlow:: TypeTracker t ) {
23
+ private API:: Node mongoEngine ( ) { result = API:: moduleImport ( "mongoengine" ) }
24
+
25
+ private API:: Node flask_MongoEngine ( ) {
26
+ result = API:: moduleImport ( "flask_mongoengine" ) .getMember ( "MongoEngine" ) .getReturn ( )
27
+ }
28
+
29
+ /** Gets a reference to a initialized `Mongo` instance. */
30
+ private API:: Node mongoInstance ( ) {
31
+ result = pyMongo ( ) or
32
+ result = flask_PyMongo ( )
33
+ }
34
+
35
+ /** Gets a reference to a initialized `Mongo` DB instance. */
36
+ private API:: Node mongoDBInstance ( ) {
37
+ result = mongoEngine ( ) .getMember ( [ "get_db" , "connect" ] ) .getReturn ( ) or
38
+ result = mongoEngine ( ) .getMember ( "connection" ) .getMember ( [ "get_db" , "connect" ] ) .getReturn ( ) or
39
+ result = flask_MongoEngine ( ) .getMember ( "get_db" ) .getReturn ( )
40
+ }
41
+
42
+ /** Gets a reference to a `Mongo` DB use. */
43
+ private DataFlow:: LocalSourceNode mongoDB ( DataFlow:: TypeTracker t ) {
32
44
t .start ( ) and
33
45
(
34
- exists ( SubscriptNode subscript | result .asCfgNode ( ) = subscript |
35
- subscript .getObject ( ) = mongoClientInstance ( ) .getAUse ( ) .asCfgNode ( )
46
+ exists ( SubscriptNode subscript |
47
+ subscript .getObject ( ) = mongoInstance ( ) .getAUse ( ) .asCfgNode ( ) and
48
+ result .asCfgNode ( ) = subscript
36
49
)
37
50
or
38
- result .( DataFlow:: AttrRead ) .getObject ( ) = mongoClientInstance ( ) .getAUse ( )
51
+ result .( DataFlow:: AttrRead ) .getObject ( ) = mongoInstance ( ) .getAUse ( )
52
+ or
53
+ result = mongoDBInstance ( ) .getAUse ( )
39
54
)
40
55
or
41
- exists ( DataFlow:: TypeTracker t2 | result = mongoClientDB ( t2 ) .track ( t2 , t ) )
56
+ exists ( DataFlow:: TypeTracker t2 | result = mongoDB ( t2 ) .track ( t2 , t ) )
42
57
}
43
58
44
- /** Gets a reference to a `MongoClient` DB. */
45
- private DataFlow:: Node mongoClientDB ( ) {
46
- mongoClientDB ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
47
- }
59
+ /** Gets a reference to a `Mongo` DB use. */
60
+ private DataFlow:: Node mongoDB ( ) { mongoDB ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
48
61
49
- /** Gets a reference to a `MongoClient ` collection. */
50
- private DataFlow:: LocalSourceNode mongoClientCollection ( DataFlow:: TypeTracker t ) {
62
+ /** Gets a reference to a `Mongo ` collection use . */
63
+ private DataFlow:: LocalSourceNode mongoCollection ( DataFlow:: TypeTracker t ) {
51
64
t .start ( ) and
52
65
(
53
66
exists ( SubscriptNode subscript | result .asCfgNode ( ) = subscript |
54
- subscript .getObject ( ) = mongoClientDB ( ) .asCfgNode ( )
67
+ subscript .getObject ( ) = mongoDB ( ) .asCfgNode ( )
55
68
)
56
69
or
57
- result .( DataFlow:: AttrRead ) .getObject ( ) = mongoClientDB ( )
70
+ result .( DataFlow:: AttrRead ) .getObject ( ) = mongoDB ( )
58
71
)
59
72
or
60
- exists ( DataFlow:: TypeTracker t2 | result = mongoClientCollection ( t2 ) .track ( t2 , t ) )
73
+ exists ( DataFlow:: TypeTracker t2 | result = mongoCollection ( t2 ) .track ( t2 , t ) )
61
74
}
62
75
63
- /** Gets a reference to a `MongoClient ` collection. */
64
- private DataFlow:: Node mongoClientCollection ( ) {
65
- mongoClientCollection ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
76
+ /** Gets a reference to a `Mongo ` collection use . */
77
+ private DataFlow:: Node mongoCollection ( ) {
78
+ mongoCollection ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
66
79
}
67
80
68
- /** This class represents names of find_* relevant MongoClient collection level operation methods. */
69
- private class MongoClientMethodNames extends string {
70
- MongoClientMethodNames ( ) {
71
- // the find_one_or_404 method is only found in the Pymongo Flask library.
81
+ /** This class represents names of find_* relevant `Mongo` collection-level operation methods. */
82
+ private class MongoCollectionMethodNames extends string {
83
+ MongoCollectionMethodNames ( ) {
72
84
this in [
73
85
"find" , "find_raw_batches" , "find_one" , "find_one_and_delete" , "find_and_modify" ,
74
86
"find_one_and_replace" , "find_one_and_update" , "find_one_or_404"
75
87
]
76
88
}
77
89
}
78
90
79
- /** Gets a reference to a `MongoClient` Collection method. */
80
- private DataFlow:: Node mongoClientMethod ( ) {
81
- result .( DataFlow:: AttrRead ) .getAttributeName ( ) instanceof MongoClientMethodNames and
82
- (
83
- result .( DataFlow:: AttrRead ) .getObject ( ) = mongoClientCollection ( ) or
84
- result .( DataFlow:: AttrRead ) = mongoClientCollection ( )
85
- )
91
+ /** Gets a reference to a `Mongo` collection method. */
92
+ private DataFlow:: Node mongoCollectionMethod ( ) {
93
+ mongoCollection ( ) in [ result .( DataFlow:: AttrRead ) , result .( DataFlow:: AttrRead ) .getObject ( ) ] and
94
+ result .( DataFlow:: AttrRead ) .getAttributeName ( ) instanceof MongoCollectionMethodNames
86
95
}
87
96
88
- /** Gets a reference to a `MongoClient` call */
89
- private class MongoClientCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
90
- MongoClientCall ( ) { this .getFunction ( ) = mongoClientMethod ( ) }
97
+ /** Gets a reference to a `Mongo` collection method call */
98
+ private class MongoCollectionCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
99
+ MongoCollectionCall ( ) { this .getFunction ( ) = mongoCollectionMethod ( ) }
91
100
92
101
override DataFlow:: Node getQuery ( ) { result = this .getArg ( 0 ) }
93
102
}
94
103
95
104
private class MongoEngineObjectsCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
96
105
MongoEngineObjectsCall ( ) {
97
106
this =
98
- API:: moduleImport ( "mongoengine" )
99
- .getMember ( [ "Document" , "EmbeddedDocument" ] )
100
- .getASubclass ( )
101
- .getMember ( "objects" )
102
- .getACall ( )
103
- }
104
-
105
- override DataFlow:: Node getQuery ( ) { result = this .getArgByName ( _) }
106
- }
107
-
108
- private class FlaskMongoEngineObjectsCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
109
- FlaskMongoEngineObjectsCall ( ) {
110
- this =
111
- API:: moduleImport ( "flask_mongoengine" )
112
- .getMember ( "MongoEngine" )
113
- .getReturn ( )
107
+ [ mongoEngine ( ) , flask_MongoEngine ( ) ]
114
108
.getMember ( [ "Document" , "EmbeddedDocument" ] )
115
109
.getASubclass ( )
116
110
.getMember ( "objects" )
@@ -120,46 +114,6 @@ private module NoSQL {
120
114
override DataFlow:: Node getQuery ( ) { result = this .getArgByName ( _) }
121
115
}
122
116
123
- private DataFlow:: Node flaskMongoEngineInstance ( ) {
124
- result = API:: moduleImport ( "flask_mongoengine" ) .getMember ( "MongoEngine" ) .getReturn ( ) .getAUse ( )
125
- }
126
-
127
- /**
128
- * A MongoEngine.Document or MongoEngine.EmbeddedDocument subclass which represents a MongoDB document.
129
- */
130
- private class FlaskMongoEngineDocumentClass extends ClassValue {
131
- FlaskMongoEngineDocumentClass ( ) {
132
- this .getASuperType ( ) .getName ( ) in [ "Document" , "EmbeddedDocument" ] and
133
- exists ( AttrNode documentClass |
134
- documentClass .getName ( ) in [ "Document" , "EmbeddedDocument" ] and
135
- documentClass .getObject ( ) = flaskMongoEngineInstance ( ) .asCfgNode ( ) and
136
- // This is super hacky. It checks to see if the class is a subclass of a flaskMongoEngineInstance.Document
137
- this .getASuperType ( )
138
- .getAReference ( )
139
- .getNode ( )
140
- .( ClassExpr )
141
- .contains ( documentClass .getNode ( ) .getObject ( ) )
142
- )
143
- }
144
- }
145
-
146
- private class FlaskMongoEngineDocumentSubclassInstanceCall extends DataFlow:: CallCfgNode ,
147
- NoSQLQuery:: Range {
148
- FlaskMongoEngineDocumentSubclassInstanceCall ( ) {
149
- exists (
150
- DataFlow:: CallCfgNode objectsCall ,
151
- FlaskMongoEngineDocumentClass flaskMongoEngineDocumentClass
152
- |
153
- objectsCall .getFunction ( ) .asExpr ( ) .( Attribute ) .getObject ( ) .getAFlowNode ( ) =
154
- flaskMongoEngineDocumentClass .getAReference ( ) and
155
- objectsCall .asCfgNode ( ) .( CallNode ) .getNode ( ) .getFunc ( ) .( Attribute ) .getName ( ) = "objects" and
156
- this = objectsCall
157
- )
158
- }
159
-
160
- override DataFlow:: Node getQuery ( ) { result = this .getArgByName ( _) }
161
- }
162
-
163
117
private class MongoSanitizerCall extends DataFlow:: CallCfgNode , NoSQLSanitizer:: Range {
164
118
MongoSanitizerCall ( ) {
165
119
this =
0 commit comments