@@ -295,6 +295,66 @@ module AiohttpWebModel {
295295 DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
296296 }
297297
298+ /**
299+ * Provides models for the `aiohttp.StreamReader` class
300+ *
301+ * See https://docs.aiohttp.org/en/stable/streams.html#aiohttp.StreamReader
302+ */
303+ module StreamReader {
304+ /**
305+ * A source of instances of `aiohttp.StreamReader`, extend this class to model new instances.
306+ *
307+ * This can include instantiations of the class, return values from function
308+ * calls, or a special parameter that will be set when functions are called by an external
309+ * library.
310+ *
311+ * Use `StreamReader::instance()` predicate to get
312+ * references to instances of `aiohttp.StreamReader`.
313+ */
314+ abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
315+
316+ /** Gets a reference to an instance of `aiohttp.StreamReader`. */
317+ private DataFlow:: LocalSourceNode instance ( DataFlow:: TypeTracker t ) {
318+ t .start ( ) and
319+ result instanceof InstanceSource
320+ or
321+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
322+ }
323+
324+ /** Gets a reference to an instance of `aiohttp.StreamReader`. */
325+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
326+
327+ /**
328+ * Taint propagation for `aiohttp.StreamReader`.
329+ */
330+ private class AiohttpStreamReaderAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
331+ override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
332+ // Methods
333+ //
334+ // TODO: When we have tools that make it easy, model these properly to handle
335+ // `meth = obj.meth; meth()`. Until then, we'll use this more syntactic approach
336+ // (since it allows us to at least capture the most common cases).
337+ nodeFrom = StreamReader:: instance ( ) and
338+ exists ( DataFlow:: AttrRead attr | attr .getObject ( ) = nodeFrom |
339+ // normal methods
340+ attr .getAttributeName ( ) in [ "read_nowait" ] and
341+ nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = attr
342+ or
343+ // async methods
344+ exists ( Await await , DataFlow:: CallCfgNode call |
345+ attr .getAttributeName ( ) in [
346+ "read" , "readany" , "readexactly" , "readline" , "readchunk" , "iter_chunked" ,
347+ "iter_any" , "iter_chunks"
348+ ] and
349+ call .getFunction ( ) = attr and
350+ await .getValue ( ) = call .asExpr ( ) and
351+ nodeTo .asExpr ( ) = await
352+ )
353+ )
354+ }
355+ }
356+ }
357+
298358 /**
299359 * A parameter that will receive an `aiohttp.web.Request` instance when a request
300360 * handler is invoked.
@@ -395,6 +455,14 @@ module AiohttpWebModel {
395455 }
396456 }
397457
458+ /** An attribute read on an `aiohttp.web.Request` that is a `aiohttp.StreamReader` instance. */
459+ class AiohttpRequestStreamReaderInstances extends StreamReader:: InstanceSource {
460+ AiohttpRequestStreamReaderInstances ( ) {
461+ this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
462+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "content" , "_payload" ]
463+ }
464+ }
465+
398466 // ---------------------------------------------------------------------------
399467 // aiohttp.web Response modeling
400468 // ---------------------------------------------------------------------------
0 commit comments