@@ -289,6 +289,78 @@ private module Django {
289
289
API:: Node subclassRef ( ) { result = any ( ModeledSubclass subclass ) .getASubclass * ( ) }
290
290
}
291
291
}
292
+
293
+ /**
294
+ * Provides models for the `django.utils.datastructures.MultiValueDict` class
295
+ *
296
+ * See
297
+ * - https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.QueryDict (subclass that has proper docs)
298
+ * - https://www.kite.com/python/docs/django.utils.datastructures.MultiValueDict
299
+ */
300
+ module MultiValueDict {
301
+ /** Gets a reference to the `django.utils.datastructures.MultiValueDict` class. */
302
+ private API:: Node classRef ( ) {
303
+ result =
304
+ API:: moduleImport ( "django" )
305
+ .getMember ( "utils" )
306
+ .getMember ( "datastructures" )
307
+ .getMember ( "MultiValueDict" )
308
+ }
309
+
310
+ /**
311
+ * A source of instances of `django.utils.datastructures.MultiValueDict`, extend this class to model new instances.
312
+ *
313
+ * This can include instantiations of the class, return values from function
314
+ * calls, or a special parameter that will be set when functions are called by an external
315
+ * library.
316
+ *
317
+ * Use the predicate `MultiValueDict::instance()` to get references to instances of `django.utils.datastructures.MultiValueDict`.
318
+ */
319
+ abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
320
+
321
+ /** A direct instantiation of `django.utils.datastructures.MultiValueDict`. */
322
+ private class ClassInstantiation extends InstanceSource , DataFlow:: CallCfgNode {
323
+ override CallNode node ;
324
+
325
+ ClassInstantiation ( ) { this = classRef ( ) .getACall ( ) }
326
+ }
327
+
328
+ /** Gets a reference to an instance of `django.utils.datastructures.MultiValueDict`. */
329
+ private DataFlow:: TypeTrackingNode instance ( DataFlow:: TypeTracker t ) {
330
+ t .start ( ) and
331
+ result instanceof InstanceSource
332
+ or
333
+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
334
+ }
335
+
336
+ /** Gets a reference to an instance of `django.utils.datastructures.MultiValueDict`. */
337
+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
338
+
339
+ /**
340
+ * Taint propagation for `django.utils.datastructures.MultiValueDict`.
341
+ */
342
+ class MultiValueDictAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
343
+ override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
344
+ // class instantiation
345
+ exists ( ClassInstantiation call |
346
+ nodeFrom = call .getArg ( 0 ) and
347
+ nodeTo = call
348
+ )
349
+ or
350
+ // Methods
351
+ //
352
+ // TODO: When we have tools that make it easy, model these properly to handle
353
+ // `meth = obj.meth; meth()`. Until then, we'll use this more syntactic approach
354
+ // (since it allows us to at least capture the most common cases).
355
+ nodeFrom = instance ( ) and
356
+ exists ( DataFlow:: AttrRead attr | attr .getObject ( ) = nodeFrom |
357
+ // methods (non-async)
358
+ attr .getAttributeName ( ) in [ "getlist" , "lists" , "popitem" , "dict" , "urlencode" ] and
359
+ nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = attr
360
+ )
361
+ }
362
+ }
363
+ }
292
364
}
293
365
294
366
/**
@@ -1922,7 +1994,6 @@ private module PrivateDjango {
1922
1994
// str / bytes
1923
1995
"body" , "path" , "path_info" , "method" , "encoding" , "content_type" ,
1924
1996
// django.http.QueryDict
1925
- // TODO: Model QueryDict
1926
1997
"GET" , "POST" ,
1927
1998
// dict[str, str]
1928
1999
"content_params" , "COOKIES" ,
@@ -1931,7 +2002,6 @@ private module PrivateDjango {
1931
2002
// HttpHeaders (case insensitive dict-like)
1932
2003
"headers" ,
1933
2004
// MultiValueDict[str, UploadedFile]
1934
- // TODO: Model MultiValueDict
1935
2005
// TODO: Model UploadedFile
1936
2006
"FILES" ,
1937
2007
// django.urls.ResolverMatch
@@ -1942,6 +2012,14 @@ private module PrivateDjango {
1942
2012
}
1943
2013
}
1944
2014
2015
+ /** An attribute read on an django request that is a `MultiValueDict` instance. */
2016
+ class DjangoHttpRequestMultiValueDictInstances extends Django:: MultiValueDict:: InstanceSource {
2017
+ DjangoHttpRequestMultiValueDictInstances ( ) {
2018
+ this .( DataFlow:: AttrRead ) .getObject ( ) = django:: http:: request:: HttpRequest:: instance ( ) and
2019
+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "GET" , "POST" , "FILES" ]
2020
+ }
2021
+ }
2022
+
1945
2023
// ---------------------------------------------------------------------------
1946
2024
// django.shortcuts.redirect
1947
2025
// ---------------------------------------------------------------------------
0 commit comments