@@ -6,67 +6,72 @@ import semmle.python.web.Http
66// a FunctionValue, so we can't use `FunctionValue.getArgumentForCall`
77// https://github.com/django/django/blob/master/django/urls/conf.py#L76
88
9- private predicate django_regex_route ( CallNode call , ControlFlowNode regex , FunctionValue view ) {
10- exists ( Value route_maker |
11- (
9+ abstract class DjangoRoute extends CallNode {
10+
11+ abstract FunctionValue getViewFunction ( ) ;
12+
13+ abstract string getANamedArgument ( ) ;
14+
15+ /**
16+ * Get the number of positional arguments that will be passed to the view.
17+ * Will only return a result if there are no named arguments.
18+ */
19+ abstract int getNumPositionalArguments ( ) ;
20+ }
21+
22+ // We need this "dummy" class, since otherwise the regex argument would not be considered a regex (RegexString is abstract)
23+ class DjangoRouteRegex extends RegexString {
24+ DjangoRouteRegex ( ) {
25+ exists ( DjangoRegexRoute route | route .getRouteArg ( ) = this .getAFlowNode ( ) )
26+ }
27+ }
28+
29+ class DjangoRegexRoute extends DjangoRoute {
30+
31+ ControlFlowNode route ;
32+ FunctionValue view ;
33+
34+ DjangoRegexRoute ( ) {
35+
36+ exists ( FunctionValue route_maker |
1237 // Django 1.x
1338 Value:: named ( "django.conf.urls.url" ) = route_maker and
14- route_maker .( FunctionValue ) . getArgumentForCall ( call , 0 ) = regex and
15- route_maker .( FunctionValue ) . getArgumentForCall ( call , 1 ) .pointsTo ( view )
39+ route_maker .getArgumentForCall ( this , 0 ) = route and
40+ route_maker .getArgumentForCall ( this , 1 ) .pointsTo ( view )
1641 )
1742 or
1843 (
1944 // Django 2.x and 3.x: https://docs.djangoproject.com/en/3.0/ref/urls/#re-path
20- Value:: named ( "django.urls.re_path" ) = route_maker and
21- route_maker .getACall ( ) = call and
45+ this = Value:: named ( "django.urls.re_path" ) .getACall ( ) and
2246 (
23- call .getArg ( 0 ) = regex
47+ route = this .getArg ( 0 )
2448 or
25- call .getArgByName ( "route" ) = regex
49+ route = this .getArgByName ( "route" )
2650
2751 ) and
2852 (
29- call .getArg ( 1 ) .pointsTo ( view )
53+ this .getArg ( 1 ) .pointsTo ( view )
3054 or
31- call .getArgByName ( "view" ) .pointsTo ( view )
55+ this .getArgByName ( "view" ) .pointsTo ( view )
3256 )
3357 )
34- )
35- }
36-
37- class DjangoRouteRegex extends RegexString {
38- DjangoRouteRegex ( ) { django_regex_route ( _, this .getAFlowNode ( ) , _) }
39- }
40-
41- abstract class DjangoRoute extends CallNode {
42-
43- abstract FunctionValue getViewFunction ( ) ;
44-
45- abstract string getANamedArgument ( ) ;
46-
47- /**
48- * Get the number of positional arguments that will be passed to the view.
49- * Will only return a result if there are no named arguments.
50- */
51- abstract int getNumPositionalArguments ( ) ;
52- }
58+ }
5359
54- class DjangoRegexRoute extends DjangoRoute {
55- DjangoRegexRoute ( ) { django_regex_route ( this , _, _) }
60+ override FunctionValue getViewFunction ( ) { result = view }
5661
57- override FunctionValue getViewFunction ( ) { django_regex_route ( this , _ , result ) }
62+ ControlFlowNode getRouteArg ( ) { result = route }
5863
5964 override string getANamedArgument ( ) {
6065 exists ( DjangoRouteRegex regex |
61- django_regex_route ( this , regex .getAFlowNode ( ) , _ ) and
62- regex .getGroupName ( _, _) = result
66+ regex .getAFlowNode ( ) = route |
67+ result = regex .getGroupName ( _, _)
6368 )
6469 }
6570
6671 override int getNumPositionalArguments ( ) {
72+ not exists ( this .getANamedArgument ( ) ) and
6773 exists ( DjangoRouteRegex regex |
68- not exists ( this .getANamedArgument ( ) ) and
69- django_regex_route ( this , regex .getAFlowNode ( ) , _) and
74+ regex .getAFlowNode ( ) = route |
7075 result = count ( regex .getGroupNumber ( _, _) )
7176 )
7277 }
0 commit comments