Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 42eceb8

Browse files
committed
Python: Handle view functions with decorators
1 parent eb7e30d commit 42eceb8

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* 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.

python/ql/src/semmle/python/frameworks/Django.qll

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,14 @@ private module Django {
19751975
}
19761976
}
19771977

1978+
/**
1979+
* Gets the last decorator call for the function `func`, if `func` has decorators.
1980+
*/
1981+
private Expr lastDecoratorCall(Function func) {
1982+
result = func.getDefinition().(FunctionExpr).getADecoratorCall() and
1983+
not exists(Call other_decorator | other_decorator.getArg(0) = result)
1984+
}
1985+
19781986
// ---------------------------------------------------------------------------
19791987
// routing modeling
19801988
// ---------------------------------------------------------------------------
@@ -1987,7 +1995,18 @@ private module Django {
19871995
*/
19881996
private DataFlow::Node djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker t, Function func) {
19891997
t.start() and
1990-
result = DataFlow::exprNode(func.getDefinition())
1998+
(
1999+
not exists(func.getADecorator()) and
2000+
result.asExpr() = func.getDefinition()
2001+
or
2002+
// If the function has decorators, we still want to model the function as being
2003+
// the request handler for a route setup. In such situations, we must track the
2004+
// last decorator call instead of the function itself.
2005+
//
2006+
// Note that this means that we blindly ignore what the decorator actually does to
2007+
// the function, which seems like an OK tradeoff.
2008+
result.asExpr() = lastDecoratorCall(func)
2009+
)
19912010
or
19922011
exists(DataFlow::TypeTracker t2 |
19932012
result = djangoRouteHandlerFunctionTracker(t2, func).track(t2, t)

python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def get(self, request, possibly_not_routed=42): # $ requestHandler routedParame
134134

135135

136136
@require_GET
137-
def with_decorator(request, foo): # $ MISSING: requestHandler routedParameter=foo
137+
def with_decorator(request, foo): # $ requestHandler routedParameter=foo
138138
pass
139139

140140
urlpatterns = [

0 commit comments

Comments
 (0)