@@ -10,6 +10,8 @@ private import semmle.python.dataflow.new.RemoteFlowSources
1010private import semmle.python.Concepts
1111private import semmle.python.ApiGraphs
1212private import semmle.python.frameworks.PEP249
13+ private import semmle.python.frameworks.internal.PoorMansFunctionResolution
14+ private import semmle.python.frameworks.internal.SelfRefMixin
1315private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
1416
1517/** Provides models for the Python standard library. */
@@ -1349,6 +1351,161 @@ private module StdlibPrivate {
13491351 }
13501352 }
13511353
1354+ // ---------------------------------------------------------------------------
1355+ // wsgiref.simple_server
1356+ // ---------------------------------------------------------------------------
1357+ /** Provides models for the `wsgiref.simple_server` module. */
1358+ private module WsgirefSimpleServer {
1359+ class WsgiServerSubclass extends Class , SelfRefMixin {
1360+ WsgiServerSubclass ( ) {
1361+ this .getABase ( ) =
1362+ API:: moduleImport ( "wsgiref" )
1363+ .getMember ( "simple_server" )
1364+ .getMember ( "WSGIServer" )
1365+ .getASubclass * ( )
1366+ .getAUse ( )
1367+ .asExpr ( )
1368+ }
1369+ }
1370+
1371+ /**
1372+ * A function that was passed to the `set_app` method of a
1373+ * `wsgiref.simple_server.WSGIServer` instance.
1374+ *
1375+ * See https://docs.python.org/3.10/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app
1376+ *
1377+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L137
1378+ * for how a request is processed and given to an application.
1379+ */
1380+ class WsgirefSimpleServerApplication extends HTTP:: Server:: RequestHandler:: Range {
1381+ WsgirefSimpleServerApplication ( ) {
1382+ exists ( DataFlow:: Node appArg , DataFlow:: CallCfgNode setAppCall |
1383+ (
1384+ setAppCall =
1385+ API:: moduleImport ( "wsgiref" )
1386+ .getMember ( "simple_server" )
1387+ .getMember ( "WSGIServer" )
1388+ .getASubclass * ( )
1389+ .getReturn ( )
1390+ .getMember ( "set_app" )
1391+ .getACall ( )
1392+ or
1393+ setAppCall
1394+ .( DataFlow:: MethodCallNode )
1395+ .calls ( any ( WsgiServerSubclass cls ) .getASelfRef ( ) , "set_app" )
1396+ ) and
1397+ appArg in [ setAppCall .getArg ( 0 ) , setAppCall .getArgByName ( "application" ) ]
1398+ |
1399+ appArg = poorMansFunctionTracker ( this )
1400+ )
1401+ }
1402+
1403+ override Parameter getARoutedParameter ( ) { none ( ) }
1404+
1405+ override string getFramework ( ) { result = "Stdlib: wsgiref.simple_server application" }
1406+ }
1407+
1408+ /**
1409+ * The parameter of a `WsgirefSimpleServerApplication` that takes the WSGI environment
1410+ * when processing a request.
1411+ *
1412+ * See https://docs.python.org/3.10/library/wsgiref.html#wsgiref.simple_server.WSGIRequestHandler.get_environ
1413+ */
1414+ class WSGIEnvirontParameter extends RemoteFlowSource:: Range , DataFlow:: ParameterNode {
1415+ WSGIEnvirontParameter ( ) {
1416+ exists ( WsgirefSimpleServerApplication func |
1417+ if func .isMethod ( )
1418+ then this .getParameter ( ) = func .getArg ( 1 )
1419+ else this .getParameter ( ) = func .getArg ( 0 )
1420+ )
1421+ }
1422+
1423+ override string getSourceType ( ) {
1424+ result = "Stdlib: wsgiref.simple_server application: WSGI environment parameter"
1425+ }
1426+ }
1427+
1428+ /**
1429+ * Gets a reference to the parameter of a `WsgirefSimpleServerApplication` that
1430+ * takes the `start_response` function.
1431+ *
1432+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1433+ */
1434+ private DataFlow:: TypeTrackingNode startResponse ( DataFlow:: TypeTracker t ) {
1435+ t .start ( ) and
1436+ exists ( WsgirefSimpleServerApplication func |
1437+ if func .isMethod ( )
1438+ then result .( DataFlow:: ParameterNode ) .getParameter ( ) = func .getArg ( 2 )
1439+ else result .( DataFlow:: ParameterNode ) .getParameter ( ) = func .getArg ( 1 )
1440+ )
1441+ or
1442+ exists ( DataFlow:: TypeTracker t2 | result = startResponse ( t2 ) .track ( t2 , t ) )
1443+ }
1444+
1445+ /**
1446+ * Gets a reference to the parameter of a `WsgirefSimpleServerApplication` that
1447+ * takes the `start_response` function.
1448+ *
1449+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1450+ */
1451+ DataFlow:: Node startResponse ( ) { startResponse ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
1452+
1453+ /**
1454+ * Gets a reference to the `write` function (that will write data to the response),
1455+ * which is the return value from calling the `start_response` function.
1456+ *
1457+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1458+ */
1459+ private DataFlow:: TypeTrackingNode writeFunction ( DataFlow:: TypeTracker t ) {
1460+ t .start ( ) and
1461+ result .( DataFlow:: CallCfgNode ) .getFunction ( ) = startResponse ( )
1462+ or
1463+ exists ( DataFlow:: TypeTracker t2 | result = writeFunction ( t2 ) .track ( t2 , t ) )
1464+ }
1465+
1466+ /**
1467+ * Gets a reference to the `write` function (that will write data to the response),
1468+ * which is the return value from calling the `start_response` function.
1469+ *
1470+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1471+ */
1472+ DataFlow:: Node writeFunction ( ) { writeFunction ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
1473+
1474+ /**
1475+ * A call to the `write` function.
1476+ *
1477+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L276
1478+ */
1479+ class WsgirefSimpleServerApplicationWriteCall extends HTTP:: Server:: HttpResponse:: Range ,
1480+ DataFlow:: CallCfgNode {
1481+ WsgirefSimpleServerApplicationWriteCall ( ) { this .getFunction ( ) = writeFunction ( ) }
1482+
1483+ override DataFlow:: Node getBody ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
1484+
1485+ override DataFlow:: Node getMimetypeOrContentTypeArg ( ) { none ( ) }
1486+
1487+ override string getMimetypeDefault ( ) { none ( ) }
1488+ }
1489+
1490+ /**
1491+ * A return from a `WsgirefSimpleServerApplication`, which is included in the response body.
1492+ */
1493+ class WsgirefSimpleServerApplicationReturn extends HTTP:: Server:: HttpResponse:: Range ,
1494+ DataFlow:: CfgNode {
1495+ WsgirefSimpleServerApplicationReturn ( ) {
1496+ exists ( WsgirefSimpleServerApplication requestHandler |
1497+ node = requestHandler .getAReturnValueFlowNode ( )
1498+ )
1499+ }
1500+
1501+ override DataFlow:: Node getBody ( ) { result = this }
1502+
1503+ override DataFlow:: Node getMimetypeOrContentTypeArg ( ) { none ( ) }
1504+
1505+ override string getMimetypeDefault ( ) { none ( ) }
1506+ }
1507+ }
1508+
13521509 // ---------------------------------------------------------------------------
13531510 // sqlite3
13541511 // ---------------------------------------------------------------------------
0 commit comments