@@ -13,6 +13,7 @@ private import semmle.python.frameworks.internal.PoorMansFunctionResolution
1313private import semmle.python.frameworks.internal.SelfRefMixin
1414private import semmle.python.frameworks.Multidict
1515private import semmle.python.frameworks.Yarl
16+ private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
1617
1718/**
1819 * INTERNAL: Do not use.
@@ -293,6 +294,65 @@ module AiohttpWebModel {
293294
294295 /** Gets a reference to an instance of `aiohttp.web.Request`. */
295296 DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
297+
298+ /**
299+ * Taint propagation for `aiohttp.web.Request`.
300+ */
301+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
302+ InstanceTaintSteps ( ) { this = "aiohttp.web.Request" }
303+
304+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
305+
306+ override string getAttributeName ( ) {
307+ result in [
308+ "url" , "rel_url" , "forwarded" , "host" , "remote" , "path" , "path_qs" , "raw_path" , "query" ,
309+ "headers" , "transport" , "cookies" , "content" , "_payload" , "content_type" , "charset" ,
310+ "http_range" , "if_modified_since" , "if_unmodified_since" , "if_range" , "match_info"
311+ ]
312+ }
313+
314+ override string getMethodName ( ) { result in [ "clone" , "get_extra_info" ] }
315+
316+ override string getAsyncMethodName ( ) {
317+ result in [ "read" , "text" , "json" , "multipart" , "post" ]
318+ }
319+ }
320+
321+ /** An attribute read on an `aiohttp.web.Request` that is a `MultiDictProxy` instance. */
322+ class AiohttpRequestMultiDictProxyInstances extends Multidict:: MultiDictProxy:: InstanceSource {
323+ AiohttpRequestMultiDictProxyInstances ( ) {
324+ this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
325+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "query" , "headers" ]
326+ or
327+ // Handle the common case of `x = await request.post()`
328+ // but don't try to handle anything else, since we don't have an easy way to do this yet.
329+ // TODO: more complete handling of `await request.post()`
330+ exists ( Await await , DataFlow:: CallCfgNode call , DataFlow:: AttrRead read |
331+ this .asExpr ( ) = await
332+ |
333+ read .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
334+ read .( DataFlow:: AttrRead ) .getAttributeName ( ) = "post" and
335+ call .getFunction ( ) = read and
336+ await .getValue ( ) = call .asExpr ( )
337+ )
338+ }
339+ }
340+
341+ /** An attribute read on an `aiohttp.web.Request` that is a `yarl.URL` instance. */
342+ class AiohttpRequestYarlUrlInstances extends Yarl:: Url:: InstanceSource {
343+ AiohttpRequestYarlUrlInstances ( ) {
344+ this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
345+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "url" , "rel_url" ]
346+ }
347+ }
348+
349+ /** An attribute read on an `aiohttp.web.Request` that is a `aiohttp.StreamReader` instance. */
350+ class AiohttpRequestStreamReaderInstances extends StreamReader:: InstanceSource {
351+ AiohttpRequestStreamReaderInstances ( ) {
352+ this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
353+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "content" , "_payload" ]
354+ }
355+ }
296356 }
297357
298358 /**
@@ -357,30 +417,20 @@ module AiohttpWebModel {
357417 /**
358418 * Taint propagation for `aiohttp.StreamReader`.
359419 */
360- private class AiohttpStreamReaderAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
361- override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
362- // Methods
363- //
364- // TODO: When we have tools that make it easy, model these properly to handle
365- // `meth = obj.meth; meth()`. Until then, we'll use this more syntactic approach
366- // (since it allows us to at least capture the most common cases).
367- nodeFrom = StreamReader:: instance ( ) and
368- exists ( DataFlow:: AttrRead attr | attr .getObject ( ) = nodeFrom |
369- // normal methods
370- attr .getAttributeName ( ) in [ "read_nowait" ] and
371- nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = attr
372- or
373- // async methods
374- exists ( Await await , DataFlow:: CallCfgNode call |
375- attr .getAttributeName ( ) in [
376- "read" , "readany" , "readexactly" , "readline" , "readchunk" , "iter_chunked" ,
377- "iter_any" , "iter_chunks"
378- ] and
379- call .getFunction ( ) = attr and
380- await .getValue ( ) = call .asExpr ( ) and
381- nodeTo .asExpr ( ) = await
382- )
383- )
420+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
421+ InstanceTaintSteps ( ) { this = "aiohttp.StreamReader" }
422+
423+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
424+
425+ override string getAttributeName ( ) { none ( ) }
426+
427+ override string getMethodName ( ) { result in [ "read_nowait" ] }
428+
429+ override string getAsyncMethodName ( ) {
430+ result in [
431+ "read" , "readany" , "readexactly" , "readline" , "readchunk" , "iter_chunked" , "iter_any" ,
432+ "iter_chunks"
433+ ]
384434 }
385435 }
386436 }
@@ -431,80 +481,6 @@ module AiohttpWebModel {
431481 }
432482 }
433483
434- /**
435- * Taint propagation for `aiohttp.web.Request`.
436- *
437- * See https://docs.aiohttp.org/en/stable/web_reference.html#request-and-base-request
438- */
439- private class AiohttpRequestAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
440- override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
441- // Methods
442- //
443- // TODO: When we have tools that make it easy, model these properly to handle
444- // `meth = obj.meth; meth()`. Until then, we'll use this more syntactic approach
445- // (since it allows us to at least capture the most common cases).
446- nodeFrom = Request:: instance ( ) and
447- exists ( DataFlow:: AttrRead attr | attr .getObject ( ) = nodeFrom |
448- // normal methods
449- attr .getAttributeName ( ) in [ "clone" , "get_extra_info" ] and
450- nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = attr
451- or
452- // async methods
453- exists ( Await await , DataFlow:: CallCfgNode call |
454- attr .getAttributeName ( ) in [ "read" , "text" , "json" , "multipart" , "post" ] and
455- call .getFunction ( ) = attr and
456- await .getValue ( ) = call .asExpr ( ) and
457- nodeTo .asExpr ( ) = await
458- )
459- )
460- or
461- // Attributes
462- nodeFrom = Request:: instance ( ) and
463- nodeTo .( DataFlow:: AttrRead ) .getObject ( ) = nodeFrom and
464- nodeTo .( DataFlow:: AttrRead ) .getAttributeName ( ) in [
465- "url" , "rel_url" , "forwarded" , "host" , "remote" , "path" , "path_qs" , "raw_path" , "query" ,
466- "headers" , "transport" , "cookies" , "content" , "_payload" , "content_type" , "charset" ,
467- "http_range" , "if_modified_since" , "if_unmodified_since" , "if_range" , "match_info"
468- ]
469- }
470- }
471-
472- /** An attribute read on an `aiohttp.web.Request` that is a `MultiDictProxy` instance. */
473- class AiohttpRequestMultiDictProxyInstances extends Multidict:: MultiDictProxy:: InstanceSource {
474- AiohttpRequestMultiDictProxyInstances ( ) {
475- this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
476- this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "query" , "headers" ]
477- or
478- // Handle the common case of `x = await request.post()`
479- // but don't try to handle anything else, since we don't have an easy way to do this yet.
480- // TODO: more complete handling of `await request.post()`
481- exists ( Await await , DataFlow:: CallCfgNode call , DataFlow:: AttrRead read |
482- this .asExpr ( ) = await
483- |
484- read .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
485- read .( DataFlow:: AttrRead ) .getAttributeName ( ) = "post" and
486- call .getFunction ( ) = read and
487- await .getValue ( ) = call .asExpr ( )
488- )
489- }
490- }
491-
492- /** An attribute read on an `aiohttp.web.Request` that is a `yarl.URL` instance. */
493- class AiohttpRequestYarlUrlInstances extends Yarl:: Url:: InstanceSource {
494- AiohttpRequestYarlUrlInstances ( ) {
495- this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
496- this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "url" , "rel_url" ]
497- }
498- }
499-
500- /** An attribute read on an `aiohttp.web.Request` that is a `aiohttp.StreamReader` instance. */
501- class AiohttpRequestStreamReaderInstances extends StreamReader:: InstanceSource {
502- AiohttpRequestStreamReaderInstances ( ) {
503- this .( DataFlow:: AttrRead ) .getObject ( ) = Request:: instance ( ) and
504- this .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "content" , "_payload" ]
505- }
506- }
507-
508484 // ---------------------------------------------------------------------------
509485 // aiohttp.web Response modeling
510486 // ---------------------------------------------------------------------------
0 commit comments