@@ -186,7 +186,7 @@ module Spife {
186
186
string kind ;
187
187
188
188
ContextInputAccess ( ) {
189
- this = request .ref ( ) .getAMethodCall ( "get" )
189
+ this = request .ref ( ) .getAMethodCall ( "get" ) and
190
190
kind = "path"
191
191
}
192
192
@@ -217,29 +217,25 @@ module Spife {
217
217
* A Spife response source, that is, the response variable used by a
218
218
* route handler.
219
219
*/
220
- private class ReplySource extends Http:: Servers:: ResponseSource instanceof DataFlow:: CallNode {
221
- ReplySource ( ) {
222
- // const reply = require("@npm/spife/reply")
220
+ private class ReplyCall extends API:: CallNode {
221
+ ReplyCall ( ) {
223
222
// reply(resp)
223
+ this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getACall ( )
224
+ or
224
225
// reply.header(resp, 'foo', 'bar')
225
- this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getACall ( ) or
226
226
this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getAMember ( ) .getACall ( )
227
227
}
228
228
229
- private DataFlow:: SourceNode reachesHandlerReturn ( DataFlow:: TypeTracker t ) {
230
- result = this and
231
- t .start ( )
232
- or
233
- exists ( DataFlow:: TypeTracker t2 | result = this .reachesHandlerReturn ( t2 ) .track ( t2 , t ) )
229
+ predicate isDirectReplyCall ( ) {
230
+ this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getACall ( )
234
231
}
235
232
236
233
/**
237
234
* Gets the route handler that provides this response.
238
235
*/
239
- override RouteHandler getRouteHandler ( ) {
236
+ RouteHandler getRouteHandler ( ) {
240
237
exists ( RouteHandler handler |
241
- handler .( DataFlow:: FunctionNode ) .getAReturn ( ) .getALocalSource ( ) =
242
- this .reachesHandlerReturn ( DataFlow:: TypeTracker:: end ( ) ) and
238
+ handler .getAReturn ( ) = this .getReturn ( ) .getAValueReachableFromSource ( ) and
243
239
result = handler
244
240
)
245
241
}
@@ -248,47 +244,46 @@ module Spife {
248
244
/**
249
245
* An HTTP header defined in a Spife response.
250
246
*/
251
- private class HeaderDefinition extends Http:: ExplicitHeaderDefinition , DataFlow :: MethodCallNode instanceof ReplySource {
252
- HeaderDefinition ( ) {
247
+ private class SingleHeaderDefinition extends Http:: ExplicitHeaderDefinition instanceof ReplyCall {
248
+ SingleHeaderDefinition ( ) {
253
249
// reply.header(RESPONSE, 'Cache-Control', 'no-cache')
254
- exists ( DataFlow:: MethodCallNode call |
255
- this .ref ( ) = call and
256
- call .getMethodName ( ) = "header" and
257
- call .getNumArgument ( ) = 3
258
- )
250
+ this .getCalleeName ( ) = "header" and
251
+ this .getNumArgument ( ) = 3
259
252
}
260
253
261
254
override predicate definesHeaderValue ( string headerName , DataFlow:: Node headerValue ) {
262
255
// reply.header(RESPONSE, 'Cache-Control', 'no-cache')
263
256
this .getNameNode ( ) .mayHaveStringValue ( headerName ) and
264
- headerValue = this .getArgument ( 2 )
257
+ headerValue = this .( DataFlow :: MethodCallNode ) . getArgument ( 2 )
265
258
}
266
259
267
- override DataFlow:: Node getNameNode ( ) { result = this .getArgument ( 1 ) }
260
+ override DataFlow:: Node getNameNode ( ) {
261
+ result = this .( DataFlow:: MethodCallNode ) .getArgument ( 1 )
262
+ }
268
263
269
- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
264
+ override RouteHandler getRouteHandler ( ) { result = this .( ReplyCall ) . getRouteHandler ( ) }
270
265
}
271
266
272
267
/**
273
268
* An invocation that sets any number of headers of the HTTP response.
274
269
*/
275
- private class MultipleHeaderDefinitions extends Http:: ExplicitHeaderDefinition , DataFlow:: CallNode {
276
- ReplySource reply ;
277
-
270
+ private class MultipleHeaderDefinitions extends Http:: ExplicitHeaderDefinition instanceof ReplyCall {
278
271
MultipleHeaderDefinitions ( ) {
279
- // reply.header(RESPONSE, {'Cache-Control': 'no-cache'})
280
- // reply(RESPONSE, {'Cache-Control': 'no-cache'})
281
- exists ( DataFlow:: CallNode call | call = [ reply .ref ( ) , reply .ref ( ) .getAMethodCall ( "header" ) ] |
282
- call .getAnArgument ( ) .getALocalSource ( ) instanceof DataFlow:: ObjectLiteralNode and
283
- this = call
284
- )
272
+ (
273
+ // reply.header(RESPONSE, {'Cache-Control': 'no-cache'})
274
+ this .getCalleeName ( ) = "header"
275
+ or
276
+ // reply(RESPONSE, {'Cache-Control': 'no-cache'})
277
+ this .isDirectReplyCall ( )
278
+ ) and
279
+ this .getAnArgument ( ) .getALocalSource ( ) instanceof DataFlow:: ObjectLiteralNode
285
280
}
286
281
287
282
/**
288
283
* Gets a reference to the multiple headers object that is to be set.
289
284
*/
290
- private DataFlow:: ObjectLiteralNode getAHeaderSource ( ) {
291
- result = this .getAnArgument ( ) .getALocalSource ( )
285
+ DataFlow:: ObjectLiteralNode getAHeaderSource ( ) {
286
+ result = this .( DataFlow :: CallNode ) . getAnArgument ( ) .getALocalSource ( )
292
287
}
293
288
294
289
override predicate definesHeaderValue ( string headerName , DataFlow:: Node headerValue ) {
@@ -302,114 +297,128 @@ module Spife {
302
297
result = this .getAHeaderSource ( ) .getAPropertyWrite ( ) .getPropertyNameExpr ( ) .flow ( )
303
298
}
304
299
305
- override RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
300
+ override RouteHandler getRouteHandler ( ) { result = this . ( ReplyCall ) .getRouteHandler ( ) }
306
301
}
307
302
308
303
/**
309
304
* A header produced by a route handler with no explicit declaration of a Content-Type.
310
305
*/
311
- private class ContentTypeRouteHandlerHeader extends Http:: ImplicitHeaderDefinition ,
312
- DataFlow:: FunctionNode instanceof RouteHandler {
306
+ private class ContentTypeRouteHandlerHeader extends Http:: ImplicitHeaderDefinition instanceof RouteHandler {
313
307
override predicate defines ( string headerName , string headerValue ) {
314
308
headerName = "content-type" and headerValue = "application/json"
315
309
}
316
310
317
- override Http :: RouteHandler getRouteHandler ( ) { result = this }
311
+ override RouteHandler getRouteHandler ( ) { result = this }
318
312
}
319
313
320
314
/**
321
315
* An HTTP cookie defined in a Spife HTTP response.
322
316
*/
323
- private class CookieDefinition extends Http:: CookieDefinition , DataFlow :: MethodCallNode {
317
+ private class CookieDefinition extends Http:: CookieDefinition instanceof ReplyCall {
324
318
CookieDefinition ( ) {
325
319
// reply.cookie(RESPONSE, 'TEST', 'FOO', {"maxAge": 1000, "httpOnly": true, "secure": true})
326
- this = any ( ReplySource r ) . ref ( ) . getAMethodCall ( "cookie" )
320
+ this . getCalleeName ( ) = "cookie"
327
321
}
328
322
329
- override DataFlow:: Node getNameArgument ( ) { result = this .getArgument ( 1 ) }
323
+ // this = any(ReplyCall r).ref().getAMethodCall("cookie")
324
+ override DataFlow:: Node getNameArgument ( ) { result = this .( ReplyCall ) .getArgument ( 1 ) }
330
325
331
- override DataFlow:: Node getValueArgument ( ) { result = this .getArgument ( 2 ) }
326
+ override DataFlow:: Node getValueArgument ( ) { result = this .( ReplyCall ) . getArgument ( 2 ) }
332
327
333
- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
328
+ override RouteHandler getRouteHandler ( ) { result = this .( ReplyCall ) . getRouteHandler ( ) }
334
329
}
335
330
336
331
/**
337
- * A response argument passed to the `reply` method .
332
+ * A response sent using a method on the `reply` object .
338
333
*/
339
- private class ReplyArgument extends Http:: ResponseSendArgument , DataFlow:: Node {
334
+ private class ReplyMethodCallArgument extends Http:: ResponseSendArgument {
335
+ ReplyCall reply ;
336
+
337
+ ReplyMethodCallArgument ( ) {
338
+ // reply.header(RESPONSE, {'Cache-Control': 'no-cache'})
339
+ reply .getCalleeName ( ) =
340
+ [ "cookie" , "link" , "header" , "headers" , "raw" , "status" , "toStream" , "vary" ] and
341
+ reply .getArgument ( 0 ) = this
342
+ }
343
+
344
+ override RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
345
+ }
346
+
347
+ /**
348
+ * A response sent using the `reply()` method.
349
+ */
350
+ private class ReplyCallArgument extends Http:: ResponseSendArgument {
351
+ ReplyCall reply ;
352
+
353
+ ReplyCallArgument ( ) {
354
+ // reply(RESPONSE, {'Cache-Control': 'no-cache'})
355
+ reply .isDirectReplyCall ( ) and
356
+ reply .getArgument ( 0 ) = this
357
+ }
358
+
359
+ override RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
360
+ }
361
+
362
+ /**
363
+ * The return statement for a route handler.
364
+ */
365
+ private class RouteHandlerReturn extends Http:: ResponseSendArgument {
340
366
RouteHandler rh ;
341
367
342
- ReplyArgument ( ) {
343
- exists ( ReplySource reply , DataFlow:: CallNode call |
344
- reply .ref ( ) = call and
345
- call .getCalleeName ( ) =
346
- [ "reply" , "cookie" , "link" , "header" , "headers" , "raw" , "status" , "toStream" , "vary" ] and
347
- this = call .getArgument ( 0 ) and
348
- rh = reply .getRouteHandler ( )
349
- )
350
- or
351
- this = rh .getAReturn ( )
368
+ RouteHandlerReturn ( ) {
369
+ this = rh .getAReturn ( ) and not this .getALocalSource ( ) instanceof ReplyCall
352
370
}
353
371
354
372
override RouteHandler getRouteHandler ( ) { result = rh }
355
373
}
356
374
357
375
/**
358
- * An expression passed to the `template` method of the reply object
359
- * as the value of a template variable.
376
+ * A call to `reply.template('template', { ... })`, seen as a template instantiation.
360
377
*/
361
- private class TemplateInput extends Http :: ResponseBody {
362
- TemplateObjectInput obj ;
378
+ private class TemplateCall extends Templating :: TemplateInstantiation :: Range instanceof ReplyCall {
379
+ TemplateCall ( ) { this . getCalleeName ( ) = "template" }
363
380
364
- TemplateInput ( ) {
365
- obj .getALocalSource ( ) .( DataFlow:: ObjectLiteralNode ) .hasPropertyWrite ( _, this )
366
- }
381
+ override DataFlow:: SourceNode getOutput ( ) { result = this }
367
382
368
- override RouteHandler getRouteHandler ( ) { result = obj .getRouteHandler ( ) }
383
+ override DataFlow:: Node getTemplateFileNode ( ) { result = this .( ReplyCall ) .getArgument ( 0 ) }
384
+
385
+ override DataFlow:: Node getTemplateParamsNode ( ) { result = this .( ReplyCall ) .getArgument ( 1 ) }
369
386
}
370
387
371
388
/**
372
389
* An object passed to the `template` method of the reply object.
373
390
*/
374
391
private class TemplateObjectInput extends DataFlow:: Node {
375
- ReplySource reply ;
392
+ TemplateCall call ;
376
393
377
- TemplateObjectInput ( ) {
378
- exists ( DataFlow:: MethodCallNode call |
379
- reply .ref ( ) = call and
380
- call .getMethodName ( ) = "template" and
381
- this = call .getArgument ( 1 )
382
- )
383
- }
394
+ TemplateObjectInput ( ) { this = call .( ReplyCall ) .getArgument ( 1 ) }
384
395
385
396
/**
386
397
* Gets the route handler that uses this object.
387
398
*/
388
- RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
399
+ RouteHandler getRouteHandler ( ) { result = call . ( ReplyCall ) .getRouteHandler ( ) }
389
400
}
390
401
391
402
/**
392
- * An invocation of the `redirect` method of an HTTP response object.
403
+ * An expression passed to the `template` method of the reply object
404
+ * as the value of a template variable.
393
405
*/
394
- private class RedirectInvocation extends Http:: RedirectInvocation , DataFlow :: MethodCallNode instanceof ReplySource {
395
- RedirectInvocation ( ) { this . ref ( ) . ( DataFlow :: MethodCallNode ) . getMethodName ( ) = "redirect" }
406
+ private class TemplateInput extends Http:: ResponseBody {
407
+ TemplateObjectInput obj ;
396
408
397
- override DataFlow :: Node getUrlArgument ( ) { result = this . getAnArgument ( ) }
409
+ TemplateInput ( ) { obj . getALocalSource ( ) . hasPropertyWrite ( _ , this ) }
398
410
399
- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
411
+ override RouteHandler getRouteHandler ( ) { result = obj .getRouteHandler ( ) }
400
412
}
401
413
402
414
/**
403
- * A call to `reply.template('template', { ... })`, seen as a template instantiation .
415
+ * An invocation of the `redirect` method of an HTTP response object .
404
416
*/
405
- private class TemplateCall extends Templating:: TemplateInstantiation:: Range ,
406
- DataFlow:: MethodCallNode instanceof ReplySource {
407
- TemplateCall ( ) { this .getMethodName ( ) = "template" }
417
+ private class RedirectInvocation extends Http:: RedirectInvocation instanceof ReplyCall {
418
+ RedirectInvocation ( ) { this .getCalleeName ( ) = "redirect" }
408
419
409
- override DataFlow:: SourceNode getOutput ( ) { result = this }
410
-
411
- override DataFlow:: Node getTemplateFileNode ( ) { result = this .getArgument ( 0 ) }
420
+ override DataFlow:: Node getUrlArgument ( ) { result = this .getAnArgument ( ) }
412
421
413
- override DataFlow :: Node getTemplateParamsNode ( ) { result = this .getArgument ( 1 ) }
422
+ override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
414
423
}
415
424
}
0 commit comments