update the predicates on Express::RouteHandler to use dataflow nodes

This commit is contained in:
Erik Krogh Kristensen
2022-03-30 17:55:45 +02:00
committed by erik-krogh
parent 4cfbf15d18
commit 8266b083d7
13 changed files with 69 additions and 68 deletions

View File

@@ -30,29 +30,31 @@ module Connect {
*
* `kind` is one of: "error", "request", "response", "next".
*/
abstract Parameter getRouteHandlerParameter(string kind);
abstract DataFlow::ParameterNode getRouteHandlerParameter(string kind);
/**
* Gets the parameter of the route handler that contains the request object.
*/
override Parameter getRequestParameter() { result = getRouteHandlerParameter("request") }
override DataFlow::ParameterNode getRequestParameter() {
result = getRouteHandlerParameter("request")
}
/**
* Gets the parameter of the route handler that contains the response object.
*/
override Parameter getResponseParameter() { result = getRouteHandlerParameter("response") }
override DataFlow::ParameterNode getResponseParameter() {
result = getRouteHandlerParameter("response")
}
}
/**
* A Connect route handler installed by a route setup.
*/
class StandardRouteHandler extends RouteHandler {
override Function astNode;
class StandardRouteHandler extends RouteHandler, DataFlow::FunctionNode {
StandardRouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
result = getRouteHandlerParameter(astNode, kind)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
result = getRouteHandlerParameter(this, kind)
}
}

View File

@@ -52,7 +52,7 @@ module ConnectExpressShared {
/**
* Holds if `function` appears to match the given signature based on parameter naming.
*/
private predicate matchesSignature(Function function, RouteHandlerSignature sig) {
private predicate matchesSignature(DataFlow::FunctionNode function, RouteHandlerSignature sig) {
function.getNumParameter() = sig.getArity() and
function.getParameter(sig.getParameterIndex("request")).getName() = ["req", "request"] and
function.getParameter(sig.getParameterIndex("response")).getName() = ["res", "response"] and
@@ -71,8 +71,8 @@ module ConnectExpressShared {
* so the caller should restrict the function accordingly.
*/
pragma[inline]
private Parameter getRouteHandlerParameter(
Function routeHandler, RouteHandlerSignature sig, string kind
private DataFlow::ParameterNode getRouteHandlerParameter(
DataFlow::FunctionNode routeHandler, RouteHandlerSignature sig, string kind
) {
result = routeHandler.getParameter(sig.getParameterIndex(kind))
}
@@ -83,7 +83,9 @@ module ConnectExpressShared {
* `kind` is one of: "error", "request", "response", "next".
*/
pragma[inline]
Parameter getRouteParameterHandlerParameter(Function routeHandler, string kind) {
DataFlow::ParameterNode getRouteParameterHandlerParameter(
DataFlow::FunctionNode routeHandler, string kind
) {
result =
getRouteHandlerParameter(routeHandler, RouteHandlerSignature::requestResponseNextParameter(),
kind)
@@ -95,7 +97,7 @@ module ConnectExpressShared {
* `kind` is one of: "error", "request", "response", "next".
*/
pragma[inline]
Parameter getRouteHandlerParameter(Function routeHandler, string kind) {
DataFlow::ParameterNode getRouteHandlerParameter(DataFlow::FunctionNode routeHandler, string kind) {
if routeHandler.getNumParameter() = 4
then
// For arity 4 there is ambiguity between (err, req, res, next) and (req, res, next, param)
@@ -115,7 +117,7 @@ module ConnectExpressShared {
*/
class RouteHandlerCandidate extends HTTP::RouteHandlerCandidate {
RouteHandlerCandidate() {
matchesSignature(astNode, _) and
matchesSignature(this, _) and
not (
// heuristic: not a class method (the server invokes this with a function call)
astNode = any(MethodDefinition def).getBody()

View File

@@ -286,14 +286,12 @@ module Express {
* The callback given to passport in PassportRouteSetup.
*/
private class PassportRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
DataFlow::ValueNode {
override Function astNode;
DataFlow::FunctionNode {
PassportRouteHandler() { this = any(PassportRouteSetup setup).getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
kind = "request" and
result = astNode.getParameter(0)
result = this.getParameter(0)
}
}
@@ -478,40 +476,41 @@ module Express {
*
* `kind` is one of: "error", "request", "response", "next", or "parameter".
*/
abstract Parameter getRouteHandlerParameter(string kind); // TODO: DataFlow::ParameterNode
abstract DataFlow::ParameterNode getRouteHandlerParameter(string kind);
/**
* Gets the parameter of the route handler that contains the request object.
*/
Parameter getRequestParameter() { result = this.getRouteHandlerParameter("request") } // TODO: DataFlow::ParameterNode
DataFlow::ParameterNode getRequestParameter() {
result = this.getRouteHandlerParameter("request")
}
/**
* Gets the parameter of the route handler that contains the response object.
*/
Parameter getResponseParameter() { result = this.getRouteHandlerParameter("response") } // TODO: DataFlow::ParameterNode
DataFlow::ParameterNode getResponseParameter() {
result = this.getRouteHandlerParameter("response")
}
/**
* Gets a request body access of this handler.
*/
Expr getARequestBodyAccess() {
result.(PropAccess).accesses(this.getARequestNode().asExpr(), "body")
} // TODO: DataFlow::Node
DataFlow::PropRead getARequestBodyAccess() { result.accesses(this.getARequestNode(), "body") }
}
/**
* An Express route handler installed by a route setup.
*/
class StandardRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
DataFlow::ValueNode {
override Function astNode;
DataFlow::FunctionNode {
RouteSetup routeSetup;
StandardRouteHandler() { this = routeSetup.getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
if routeSetup.isParameterHandler()
then result = getRouteParameterHandlerParameter(astNode, kind)
else result = getRouteHandlerParameter(astNode, kind)
then result = getRouteParameterHandlerParameter(this, kind)
else result = getRouteHandlerParameter(this, kind)
}
}
@@ -540,7 +539,7 @@ module Express {
RouteHandler rh;
ExplicitResponseSource() {
this = DataFlow::parameterNode(rh.getResponseParameter())
this = rh.getResponseParameter()
or
isChainableResponseMethodCall(rh, this.asExpr())
}
@@ -570,7 +569,7 @@ module Express {
private class ExplicitRequestSource extends RequestSource {
RouteHandler rh;
ExplicitRequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
ExplicitRequestSource() { this = rh.getRequestParameter() }
/**
* Gets the route handler that handles this request.
@@ -637,7 +636,7 @@ module Express {
ParamHandlerInputAccess() {
exists(RouteSetup setup | rh = setup.getARouteHandler() |
this = DataFlow::parameterNode(rh.getRouteHandlerParameter("parameter"))
this = rh.getRouteHandlerParameter("parameter")
)
}
@@ -778,7 +777,8 @@ module Express {
* An access to the HTTP request body.
*/
class RequestBodyAccess extends Expr {
RequestBodyAccess() { any(RouteHandler h).getARequestBodyAccess() = this }
// TODO: DataFlow::Node
RequestBodyAccess() { any(RouteHandler h).getARequestBodyAccess().asExpr() = this }
}
abstract private class HeaderDefinition extends HTTP::Servers::StandardHeaderDefinition {
@@ -1049,10 +1049,10 @@ module Express {
TrackedRouteHandlerCandidateWithSetup() { this = routeSetup.getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
if routeSetup.isParameterHandler()
then result = getRouteParameterHandlerParameter(astNode, kind)
else result = getRouteHandlerParameter(astNode, kind)
then result = getRouteParameterHandlerParameter(this, kind)
else result = getRouteHandlerParameter(this, kind)
}
}

View File

@@ -216,15 +216,13 @@ module Firebase {
* A function used as a route handler.
*/
private class RouteHandler extends Express::RouteHandler, HTTP::Servers::StandardRouteHandler,
DataFlow::ValueNode {
override Function astNode;
DataFlow::FunctionNode {
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
kind = "request" and result = astNode.getParameter(0)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
kind = "request" and result = this.getParameter(0)
or
kind = "response" and result = astNode.getParameter(1)
kind = "response" and result = this.getParameter(1)
}
}
}

View File

@@ -83,16 +83,12 @@ private module HttpProxy {
)
}
override Parameter getRequestParameter() {
exists(int req | routeHandlingEventHandler(event, req, _) |
result = getFunction().getParameter(req)
)
override DataFlow::ParameterNode getRequestParameter() {
exists(int req | routeHandlingEventHandler(event, req, _) | result = getParameter(req))
}
override Parameter getResponseParameter() {
exists(int res | routeHandlingEventHandler(event, _, res) |
result = getFunction().getParameter(res)
)
override DataFlow::ParameterNode getResponseParameter() {
exists(int res | routeHandlingEventHandler(event, _, res) | result = getParameter(res))
}
}
}

View File

@@ -22,8 +22,8 @@ private module LiveServer {
class RouteHandler extends Connect::RouteHandler, DataFlow::FunctionNode {
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
override Parameter getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(astNode, kind)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
}
}

View File

@@ -230,10 +230,10 @@ module NextJS {
)
}
override Parameter getRouteHandlerParameter(string kind) {
kind = "request" and result = this.getFunction().getParameter(0)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
kind = "request" and result = this.getParameter(0)
or
kind = "response" and result = this.getFunction().getParameter(1)
kind = "response" and result = this.getParameter(1)
}
}

View File

@@ -114,12 +114,12 @@ module NodeJSLib {
/**
* Gets the parameter of the route handler that contains the request object.
*/
Parameter getRequestParameter() { result = this.getFunction().getParameter(0) }
DataFlow::ParameterNode getRequestParameter() { result = this.getParameter(0) }
/**
* Gets the parameter of the route handler that contains the response object.
*/
Parameter getResponseParameter() { result = this.getFunction().getParameter(1) }
DataFlow::ParameterNode getResponseParameter() { result = this.getParameter(1) }
}
/**
@@ -141,7 +141,7 @@ module NodeJSLib {
private class StandardResponseSource extends ResponseSource {
RouteHandler rh;
StandardResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) }
StandardResponseSource() { this = rh.getResponseParameter() }
/**
* Gets the route handler that provides this response.
@@ -161,7 +161,7 @@ module NodeJSLib {
private class StandardRequestSource extends RequestSource {
RouteHandler rh;
StandardRequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
StandardRequestSource() { this = rh.getRequestParameter() }
/**
* Gets the route handler that handles this request.

View File

@@ -29,8 +29,8 @@ private class PromotedExpressCandidate extends Express::RouteHandler,
HTTP::Servers::StandardRouteHandler {
PromotedExpressCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate }
override Parameter getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
}
}
@@ -41,7 +41,7 @@ private class PromotedConnectCandidate extends Connect::RouteHandler,
HTTP::Servers::StandardRouteHandler {
PromotedConnectCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate }
override Parameter getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind)
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
}
}

View File

@@ -199,7 +199,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
rateLimiterClassName.matches("RateLimiter%") and
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
request = getRouteHandlerParameter(this, "request") and
request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().asSink())
)
}

View File

@@ -1,5 +1,7 @@
import javascript
query predicate test_RouteHandler(Express::RouteHandler rh, Parameter res0, Parameter res1) {
query predicate test_RouteHandler(
Express::RouteHandler rh, DataFlow::ParameterNode res0, DataFlow::ParameterNode res1
) {
res0 = rh.getRequestParameter() and res1 = rh.getResponseParameter()
}

View File

@@ -1,5 +1,5 @@
import javascript
query predicate test_RouteHandler_getARequestBodyAccess(Express::RouteHandler rh, Expr res) {
query predicate test_RouteHandler_getARequestBodyAccess(Express::RouteHandler rh, DataFlow::Node res) {
res = rh.getARequestBodyAccess()
}

View File

@@ -1,7 +1,8 @@
import javascript
query predicate test_StandardRouteHandler(
Express::StandardRouteHandler rh, DataFlow::Node res0, SimpleParameter res1, SimpleParameter res2
Express::StandardRouteHandler rh, DataFlow::Node res0, DataFlow::ParameterNode res1,
DataFlow::ParameterNode res2
) {
res0 = rh.getServer() and res1 = rh.getRequestParameter() and res2 = rh.getResponseParameter()
}