@@ -186,7 +186,7 @@ module Spife {
186186 string kind ;
187187
188188 ContextInputAccess ( ) {
189- this = request .ref ( ) .getAMethodCall ( "get" )
189+ this = request .ref ( ) .getAMethodCall ( "get" ) and
190190 kind = "path"
191191 }
192192
@@ -217,29 +217,25 @@ module Spife {
217217 * A Spife response source, that is, the response variable used by a
218218 * route handler.
219219 */
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 ( ) {
223222 // reply(resp)
223+ this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getACall ( )
224+ or
224225 // reply.header(resp, 'foo', 'bar')
225- this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getACall ( ) or
226226 this = API:: moduleImport ( [ "@npm/spife/reply" , "spife/reply" ] ) .getAMember ( ) .getACall ( )
227227 }
228228
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 ( )
234231 }
235232
236233 /**
237234 * Gets the route handler that provides this response.
238235 */
239- override RouteHandler getRouteHandler ( ) {
236+ RouteHandler getRouteHandler ( ) {
240237 exists ( RouteHandler handler |
241- handler .( DataFlow:: FunctionNode ) .getAReturn ( ) .getALocalSource ( ) =
242- this .reachesHandlerReturn ( DataFlow:: TypeTracker:: end ( ) ) and
238+ handler .getAReturn ( ) = this .getReturn ( ) .getAValueReachableFromSource ( ) and
243239 result = handler
244240 )
245241 }
@@ -248,47 +244,46 @@ module Spife {
248244 /**
249245 * An HTTP header defined in a Spife response.
250246 */
251- private class HeaderDefinition extends Http:: ExplicitHeaderDefinition , DataFlow :: MethodCallNode instanceof ReplySource {
252- HeaderDefinition ( ) {
247+ private class SingleHeaderDefinition extends Http:: ExplicitHeaderDefinition instanceof ReplyCall {
248+ SingleHeaderDefinition ( ) {
253249 // 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
259252 }
260253
261254 override predicate definesHeaderValue ( string headerName , DataFlow:: Node headerValue ) {
262255 // reply.header(RESPONSE, 'Cache-Control', 'no-cache')
263256 this .getNameNode ( ) .mayHaveStringValue ( headerName ) and
264- headerValue = this .getArgument ( 2 )
257+ headerValue = this .( DataFlow :: MethodCallNode ) . getArgument ( 2 )
265258 }
266259
267- override DataFlow:: Node getNameNode ( ) { result = this .getArgument ( 1 ) }
260+ override DataFlow:: Node getNameNode ( ) {
261+ result = this .( DataFlow:: MethodCallNode ) .getArgument ( 1 )
262+ }
268263
269- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
264+ override RouteHandler getRouteHandler ( ) { result = this .( ReplyCall ) . getRouteHandler ( ) }
270265 }
271266
272267 /**
273268 * An invocation that sets any number of headers of the HTTP response.
274269 */
275- private class MultipleHeaderDefinitions extends Http:: ExplicitHeaderDefinition , DataFlow:: CallNode {
276- ReplySource reply ;
277-
270+ private class MultipleHeaderDefinitions extends Http:: ExplicitHeaderDefinition instanceof ReplyCall {
278271 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
285280 }
286281
287282 /**
288283 * Gets a reference to the multiple headers object that is to be set.
289284 */
290- private DataFlow:: ObjectLiteralNode getAHeaderSource ( ) {
291- result = this .getAnArgument ( ) .getALocalSource ( )
285+ DataFlow:: ObjectLiteralNode getAHeaderSource ( ) {
286+ result = this .( DataFlow :: CallNode ) . getAnArgument ( ) .getALocalSource ( )
292287 }
293288
294289 override predicate definesHeaderValue ( string headerName , DataFlow:: Node headerValue ) {
@@ -302,114 +297,128 @@ module Spife {
302297 result = this .getAHeaderSource ( ) .getAPropertyWrite ( ) .getPropertyNameExpr ( ) .flow ( )
303298 }
304299
305- override RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
300+ override RouteHandler getRouteHandler ( ) { result = this . ( ReplyCall ) .getRouteHandler ( ) }
306301 }
307302
308303 /**
309304 * A header produced by a route handler with no explicit declaration of a Content-Type.
310305 */
311- private class ContentTypeRouteHandlerHeader extends Http:: ImplicitHeaderDefinition ,
312- DataFlow:: FunctionNode instanceof RouteHandler {
306+ private class ContentTypeRouteHandlerHeader extends Http:: ImplicitHeaderDefinition instanceof RouteHandler {
313307 override predicate defines ( string headerName , string headerValue ) {
314308 headerName = "content-type" and headerValue = "application/json"
315309 }
316310
317- override Http :: RouteHandler getRouteHandler ( ) { result = this }
311+ override RouteHandler getRouteHandler ( ) { result = this }
318312 }
319313
320314 /**
321315 * An HTTP cookie defined in a Spife HTTP response.
322316 */
323- private class CookieDefinition extends Http:: CookieDefinition , DataFlow :: MethodCallNode {
317+ private class CookieDefinition extends Http:: CookieDefinition instanceof ReplyCall {
324318 CookieDefinition ( ) {
325319 // reply.cookie(RESPONSE, 'TEST', 'FOO', {"maxAge": 1000, "httpOnly": true, "secure": true})
326- this = any ( ReplySource r ) . ref ( ) . getAMethodCall ( "cookie" )
320+ this . getCalleeName ( ) = "cookie"
327321 }
328322
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 ) }
330325
331- override DataFlow:: Node getValueArgument ( ) { result = this .getArgument ( 2 ) }
326+ override DataFlow:: Node getValueArgument ( ) { result = this .( ReplyCall ) . getArgument ( 2 ) }
332327
333- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
328+ override RouteHandler getRouteHandler ( ) { result = this .( ReplyCall ) . getRouteHandler ( ) }
334329 }
335330
336331 /**
337- * A response argument passed to the `reply` method .
332+ * A response sent using a method on the `reply` object .
338333 */
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 {
340366 RouteHandler rh ;
341367
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
352370 }
353371
354372 override RouteHandler getRouteHandler ( ) { result = rh }
355373 }
356374
357375 /**
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.
360377 */
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" }
363380
364- TemplateInput ( ) {
365- obj .getALocalSource ( ) .( DataFlow:: ObjectLiteralNode ) .hasPropertyWrite ( _, this )
366- }
381+ override DataFlow:: SourceNode getOutput ( ) { result = this }
367382
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 ) }
369386 }
370387
371388 /**
372389 * An object passed to the `template` method of the reply object.
373390 */
374391 private class TemplateObjectInput extends DataFlow:: Node {
375- ReplySource reply ;
392+ TemplateCall call ;
376393
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 ) }
384395
385396 /**
386397 * Gets the route handler that uses this object.
387398 */
388- RouteHandler getRouteHandler ( ) { result = reply .getRouteHandler ( ) }
399+ RouteHandler getRouteHandler ( ) { result = call . ( ReplyCall ) .getRouteHandler ( ) }
389400 }
390401
391402 /**
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.
393405 */
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 ;
396408
397- override DataFlow :: Node getUrlArgument ( ) { result = this . getAnArgument ( ) }
409+ TemplateInput ( ) { obj . getALocalSource ( ) . hasPropertyWrite ( _ , this ) }
398410
399- override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
411+ override RouteHandler getRouteHandler ( ) { result = obj .getRouteHandler ( ) }
400412 }
401413
402414 /**
403- * A call to `reply.template('template', { ... })`, seen as a template instantiation .
415+ * An invocation of the `redirect` method of an HTTP response object .
404416 */
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" }
408419
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 ( ) }
412421
413- override DataFlow :: Node getTemplateParamsNode ( ) { result = this .getArgument ( 1 ) }
422+ override RouteHandler getRouteHandler ( ) { result = this .getRouteHandler ( ) }
414423 }
415424}
0 commit comments