1+ /**
2+ * Provides classes and predicates for reasoning about code using the Firebase API.
3+ */
14import javascript
25
36module Firebase {
4-
57 /** Gets a reference to the firebase API object. */
68 private DataFlow:: SourceNode firebase ( DataFlow:: TypeTracker t ) {
79 t .start ( ) and
@@ -18,7 +20,7 @@ module Firebase {
1820 )
1921 }
2022
21- /** Gets a reference to the firebase API object. */
23+ /** Gets a reference to the ` firebase/app` or `firebase-admin` API object. */
2224 DataFlow:: SourceNode firebase ( ) {
2325 result = firebase ( _)
2426 }
@@ -31,7 +33,7 @@ module Firebase {
3133 result = initApp ( t2 ) .track ( t2 , t )
3234 )
3335 }
34-
36+
3537 /**
3638 * Gets a reference to a firebase app, either the `firebase` object or an
3739 * app created explicitly with `initializeApp()`.
@@ -40,96 +42,188 @@ module Firebase {
4042 result = firebase ( _) or result = initApp ( _)
4143 }
4244
43- /** Gets a reference to a firebase database object, such as `firebase.database()`. */
44- private DataFlow:: SourceNode database ( DataFlow:: TypeTracker t ) {
45- result = app ( ) .getAMethodCall ( "database" ) and t .start ( )
46- or
47- exists ( DataFlow:: TypeTracker t2 |
48- result = database ( t2 ) .track ( t2 , t )
49- )
50- }
51-
52- /** Gets a reference to a firebase database object, such as `firebase.database()`. */
53- DataFlow:: SourceNode database ( ) {
54- result = database ( _)
55- }
56-
57- /** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
58- DataFlow:: SourceNode ref ( DataFlow:: TypeTracker t ) {
59- t .start ( ) and
60- (
61- exists ( string name | result = database ( ) .getAMethodCall ( name ) |
62- name = "ref" or
63- name = "refFromURL"
45+ module Database {
46+
47+ /** Gets a reference to a firebase database object, such as `firebase.database()`. */
48+ private DataFlow:: SourceNode database ( DataFlow:: TypeTracker t ) {
49+ result = app ( ) .getAMethodCall ( "database" ) and t .start ( )
50+ or
51+ exists ( DataFlow:: TypeTracker t2 |
52+ result = database ( t2 ) .track ( t2 , t )
53+ )
54+ }
55+
56+ /** Gets a reference to a firebase database object, such as `firebase.database()`. */
57+ DataFlow:: SourceNode database ( ) {
58+ result = database ( _)
59+ }
60+
61+ /** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
62+ DataFlow:: SourceNode ref ( DataFlow:: TypeTracker t ) {
63+ t .start ( ) and
64+ (
65+ exists ( string name | result = database ( ) .getAMethodCall ( name ) |
66+ name = "ref" or
67+ name = "refFromURL"
68+ )
69+ or
70+ exists ( string name | result = ref ( _) .getAMethodCall ( name ) |
71+ name = "push" or
72+ name = "child"
73+ )
74+ or
75+ exists ( string name | result = ref ( _) .getAPropertyRead ( name ) |
76+ name = "parent" or
77+ name = "root"
78+ )
79+ or
80+ result = snapshot ( ) .getAPropertyRead ( "ref" )
6481 )
6582 or
66- exists ( string name | result = ref ( _) .getAMethodCall ( name ) |
67- name = "push" or
68- name = "child"
83+ exists ( DataFlow:: TypeTracker t2 |
84+ result = ref ( t2 ) .track ( t2 , t )
85+ )
86+ }
87+
88+ /** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
89+ DataFlow:: SourceNode ref ( ) {
90+ result = ref ( _)
91+ }
92+
93+ /** Gets a node that refers to a `Query` or `Reference` object. */
94+ DataFlow:: SourceNode query ( DataFlow:: TypeTracker t ) {
95+ t .start ( ) and
96+ (
97+ result = ref ( t ) // a Reference can be used as a Query
98+ or
99+ exists ( string name | result = query ( _) .getAMethodCall ( name ) |
100+ name = "endAt" or
101+ name = "limitTo" + any ( string s ) or
102+ name = "orderBy" + any ( string s ) or
103+ name = "startAt"
104+ )
69105 )
70106 or
71- exists ( string name | result = ref ( _) .getAPropertyRead ( name ) |
72- name = "parent" or
73- name = "root"
107+ exists ( DataFlow:: TypeTracker t2 |
108+ result = query ( t2 ) .track ( t2 , t )
74109 )
110+ }
111+
112+ /** Gets a node that refers to a `Query` or `Reference` object. */
113+ DataFlow:: SourceNode query ( ) {
114+ result = query ( _)
115+ }
116+
117+ /**
118+ * A call of form `query.on(...)` or `query.once(...)`.
119+ */
120+ class QueryListenCall extends DataFlow:: MethodCallNode {
121+ QueryListenCall ( ) {
122+ this = query ( ) .getAMethodCall ( ) and
123+ ( getMethodName ( ) = "on" or getMethodName ( ) = "once" )
124+ }
125+
126+ DataFlow:: Node getCallbackNode ( ) {
127+ result = getArgument ( 1 )
128+ }
129+ }
130+
131+ /**
132+ * Gets a node that is passed as the callback to a `Reference.transaction` call.
133+ */
134+ DataFlow:: SourceNode transactionCallback ( DataFlow:: TypeTracker t ) {
135+ t .start ( ) and
136+ result = ref ( ) .getAMethodCall ( "transaction" ) .getArgument ( 0 ) .getALocalSource ( )
75137 or
76- result = snapshot ( ) .getAPropertyRead ( "ref" )
77- )
78- or
79- exists ( DataFlow:: TypeTracker t2 |
80- result = ref ( t2 ) .track ( t2 , t )
81- )
138+ exists ( DataFlow:: TypeTracker t2 |
139+ result = transactionCallback ( t2 ) .backtrack ( t2 , t )
140+ )
141+ }
142+
143+ /**
144+ * Gets a node that is passed as the callback to a `Reference.transaction` call.
145+ */
146+ DataFlow:: SourceNode transactionCallback ( ) {
147+ result = transactionCallback ( _)
148+ }
82149 }
83150
84- /** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
85- DataFlow:: SourceNode ref ( ) {
86- result = ref ( _)
87- }
151+ /**
152+ * Provides predicates for reasoning about the the Firebase Cloud Functions API,
153+ * sometimes referred to just as just "Firebase Functions".
154+ */
155+ module CloudFunctions {
156+ /** Gets a reference to the Cloud Functions namespace. */
157+ DataFlow:: SourceNode namespace ( DataFlow:: TypeTracker t ) {
158+ t .start ( ) and
159+ result = DataFlow:: moduleImport ( "firebase-functions" )
160+ or
161+ exists ( DataFlow:: TypeTracker t2 |
162+ result = namespace ( t2 ) .track ( t2 , t )
163+ )
164+ }
165+
166+ /** Gets a reference to the Cloud Functions namespace. */
167+ DataFlow:: SourceNode namespace ( ) {
168+ result = namespace ( _)
169+ }
88170
89- /** Gets a node that refers to a `Query` or `Reference` object. */
90- DataFlow:: SourceNode query ( DataFlow:: TypeTracker t ) {
91- t .start ( ) and
92- (
93- result = ref ( t ) // a Reference can be used as a Query
171+ /** Gets a reference to a Cloud Functions database object. */
172+ DataFlow:: SourceNode database ( DataFlow:: TypeTracker t ) {
173+ t .start ( ) and
174+ result = namespace ( ) .getAPropertyRead ( "database" )
94175 or
95- exists ( string name | result = query ( _) .getAMethodCall ( name ) |
96- name = "endAt" or
97- name = "limitTo" + any ( string s ) or
98- name = "orderBy" + any ( string s ) or
99- name = "startAt"
176+ exists ( DataFlow:: TypeTracker t2 |
177+ result = database ( t2 ) .track ( t2 , t )
100178 )
101- )
102- or
103- exists ( DataFlow:: TypeTracker t2 |
104- result = query ( t2 ) .track ( t2 , t )
105- )
106- }
179+ }
107180
108- /** Gets a node that refers to a `Query` or `Reference` object. */
109- DataFlow:: SourceNode query ( ) {
110- result = query ( _)
111- }
112-
113- /**
114- * A call of form `query.on(...)` or `query.once(...)`.
115- */
116- class QueryListenCall extends DataFlow:: MethodCallNode {
117- QueryListenCall ( ) {
118- this = query ( ) .getAMethodCall ( ) and
119- ( getMethodName ( ) = "on" or getMethodName ( ) = "once" )
181+ /** Gets a reference to a Cloud Functions database object. */
182+ DataFlow:: SourceNode database ( ) {
183+ result = database ( _)
184+ }
185+
186+ /** Gets a dataflow node holding a `RefBuilder` object. */
187+ DataFlow:: SourceNode refBuilder ( DataFlow:: TypeTracker t ) {
188+ t .start ( ) and
189+ result = database ( ) .getAMethodCall ( "ref" )
190+ or
191+ exists ( DataFlow:: TypeTracker t2 |
192+ result = refBuilder ( t2 ) .track ( t2 , t )
193+ )
120194 }
121195
122- DataFlow:: Node getCallbackNode ( ) {
123- result = getArgument ( 1 )
196+ /** Gets a dataflow node holding a `RefBuilder` object. */
197+ DataFlow:: SourceNode ref ( ) {
198+ result = refBuilder ( _)
124199 }
125- }
126200
201+ /** Gets a call that registers a listener on a `RefBuilder`, such as `ref.onCreate(...)`. */
202+ class RefBuilderListenCall extends DataFlow:: MethodCallNode {
203+ RefBuilderListenCall ( ) {
204+ this = ref ( ) .getAMethodCall ( ) and
205+ getMethodName ( ) = "on" + any ( string s )
206+ }
207+
208+ /**
209+ * Gets the dataflow node holding the listener callback.
210+ */
211+ DataFlow:: Node getCallbackNode ( ) {
212+ result = getArgument ( 0 )
213+ }
214+ }
215+ }
216+
127217 /**
128218 * Gets a value that will be invoked with a `DataSnapshot` value as its first parameter.
129219 */
130220 DataFlow:: SourceNode snapshotCallback ( DataFlow:: TypeTracker t ) {
131221 t .start ( ) and
132- result = any ( QueryListenCall call ) .getCallbackNode ( ) .getALocalSource ( )
222+ (
223+ result = any ( Database:: QueryListenCall call ) .getCallbackNode ( ) .getALocalSource ( )
224+ or
225+ result = any ( CloudFunctions:: RefBuilderListenCall call ) .getCallbackNode ( ) .getALocalSource ( )
226+ )
133227 or
134228 exists ( DataFlow:: TypeTracker t2 |
135229 result = snapshotCallback ( t2 ) .backtrack ( t2 , t )
@@ -151,7 +245,7 @@ module Firebase {
151245 (
152246 result = snapshotCallback ( ) .( DataFlow:: FunctionNode ) .getParameter ( 0 )
153247 or
154- result instanceof QueryListenCall // returns promise
248+ result instanceof Database :: QueryListenCall // returns promise
155249 or
156250 result = snapshot ( _) .getAMethodCall ( "child" )
157251 or
@@ -161,7 +255,7 @@ module Firebase {
161255 promiseTaintStep ( snapshot ( t ) , result )
162256 or
163257 exists ( DataFlow:: TypeTracker t2 |
164- result = ref ( t2 ) .track ( t2 , t )
258+ result = snapshot ( t2 ) .track ( t2 , t )
165259 )
166260 }
167261
@@ -174,32 +268,16 @@ module Firebase {
174268 }
175269
176270 /**
177- * Gets a node that is passed as the callback to a `Reference.transaction` call .
271+ * A reference to a value obtained from a Firebase database .
178272 */
179- DataFlow:: SourceNode transactionCallback ( DataFlow:: TypeTracker t ) {
180- t .start ( ) and
181- result = ref ( ) .getAMethodCall ( "transaction" ) .getArgument ( 0 ) .getALocalSource ( )
182- or
183- exists ( DataFlow:: TypeTracker t2 |
184- result = transactionCallback ( t2 ) .backtrack ( t2 , t )
185- )
186- }
187-
188- /**
189- * Gets a node that is passed as the callback to a `Reference.transaction` call.
190- */
191- DataFlow:: SourceNode transactionCallback ( ) {
192- result = transactionCallback ( _)
193- }
194-
195273 class FirebaseVal extends RemoteFlowSource {
196274 FirebaseVal ( ) {
197275 exists ( string name | this = snapshot ( ) .getAMethodCall ( name ) |
198276 name = "val" or
199277 name = "exportVal"
200278 )
201279 or
202- this = transactionCallback ( ) .( DataFlow:: FunctionNode ) .getParameter ( 0 )
280+ this = Database :: transactionCallback ( ) .( DataFlow:: FunctionNode ) .getParameter ( 0 )
203281 }
204282
205283 override string getSourceType ( ) {
0 commit comments