Python: Handle view functions with decorators

This commit is contained in:
Rasmus Wriedt Larsen
2021-02-10 15:47:55 +01:00
parent eb7e30d472
commit 42eceb80bd
3 changed files with 23 additions and 2 deletions

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Improved modeling of `django` to recognize request handlers functions that are decorated (for example with `django.views.decorators.http.require_GET`). This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request.

View File

@@ -1975,6 +1975,14 @@ private module Django {
}
}
/**
* Gets the last decorator call for the function `func`, if `func` has decorators.
*/
private Expr lastDecoratorCall(Function func) {
result = func.getDefinition().(FunctionExpr).getADecoratorCall() and
not exists(Call other_decorator | other_decorator.getArg(0) = result)
}
// ---------------------------------------------------------------------------
// routing modeling
// ---------------------------------------------------------------------------
@@ -1987,7 +1995,18 @@ private module Django {
*/
private DataFlow::Node djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker t, Function func) {
t.start() and
result = DataFlow::exprNode(func.getDefinition())
(
not exists(func.getADecorator()) and
result.asExpr() = func.getDefinition()
or
// If the function has decorators, we still want to model the function as being
// the request handler for a route setup. In such situations, we must track the
// last decorator call instead of the function itself.
//
// Note that this means that we blindly ignore what the decorator actually does to
// the function, which seems like an OK tradeoff.
result.asExpr() = lastDecoratorCall(func)
)
or
exists(DataFlow::TypeTracker t2 |
result = djangoRouteHandlerFunctionTracker(t2, func).track(t2, t)

View File

@@ -134,7 +134,7 @@ class PossiblyNotRouted(View):
@require_GET
def with_decorator(request, foo): # $ MISSING: requestHandler routedParameter=foo
def with_decorator(request, foo): # $ requestHandler routedParameter=foo
pass
urlpatterns = [