@@ -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. */
@@ -1316,6 +1318,161 @@ private module StdlibPrivate {
13161318 }
13171319 }
13181320
1321+ // ---------------------------------------------------------------------------
1322+ // wsgiref.simple_server
1323+ // ---------------------------------------------------------------------------
1324+ /** Provides models for the `wsgiref.simple_server` module. */
1325+ private module WsgirefSimpleServer {
1326+ class WsgiServerSubclass extends Class , SelfRefMixin {
1327+ WsgiServerSubclass ( ) {
1328+ this .getABase ( ) =
1329+ API:: moduleImport ( "wsgiref" )
1330+ .getMember ( "simple_server" )
1331+ .getMember ( "WSGIServer" )
1332+ .getASubclass * ( )
1333+ .getAUse ( )
1334+ .asExpr ( )
1335+ }
1336+ }
1337+
1338+ /**
1339+ * A function that was passed to the `set_app` method of a
1340+ * `wsgiref.simple_server.WSGIServer` instance.
1341+ *
1342+ * See https://docs.python.org/3.10/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app
1343+ *
1344+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L137
1345+ * for how a request is processed and given to an application.
1346+ */
1347+ class WsgirefSimpleServerApplication extends HTTP:: Server:: RequestHandler:: Range {
1348+ WsgirefSimpleServerApplication ( ) {
1349+ exists ( DataFlow:: Node appArg , DataFlow:: CallCfgNode setAppCall |
1350+ (
1351+ setAppCall =
1352+ API:: moduleImport ( "wsgiref" )
1353+ .getMember ( "simple_server" )
1354+ .getMember ( "WSGIServer" )
1355+ .getASubclass * ( )
1356+ .getReturn ( )
1357+ .getMember ( "set_app" )
1358+ .getACall ( )
1359+ or
1360+ setAppCall
1361+ .( DataFlow:: MethodCallNode )
1362+ .calls ( any ( WsgiServerSubclass cls ) .getASelfRef ( ) , "set_app" )
1363+ ) and
1364+ appArg in [ setAppCall .getArg ( 0 ) , setAppCall .getArgByName ( "application" ) ]
1365+ |
1366+ appArg = poorMansFunctionTracker ( this )
1367+ )
1368+ }
1369+
1370+ override Parameter getARoutedParameter ( ) { none ( ) }
1371+
1372+ override string getFramework ( ) { result = "Stdlib: wsgiref.simple_server application" }
1373+ }
1374+
1375+ /**
1376+ * The parameter of a `WsgirefSimpleServerApplication` that takes the WSGI environment
1377+ * when processing a request.
1378+ *
1379+ * See https://docs.python.org/3.10/library/wsgiref.html#wsgiref.simple_server.WSGIRequestHandler.get_environ
1380+ */
1381+ class WSGIEnvirontParameter extends RemoteFlowSource:: Range , DataFlow:: ParameterNode {
1382+ WSGIEnvirontParameter ( ) {
1383+ exists ( WsgirefSimpleServerApplication func |
1384+ if func .isMethod ( )
1385+ then this .getParameter ( ) = func .getArg ( 1 )
1386+ else this .getParameter ( ) = func .getArg ( 0 )
1387+ )
1388+ }
1389+
1390+ override string getSourceType ( ) {
1391+ result = "Stdlib: wsgiref.simple_server application: WSGI environment parameter"
1392+ }
1393+ }
1394+
1395+ /**
1396+ * Gets a reference to the parameter of a `WsgirefSimpleServerApplication` that
1397+ * takes the `start_response` function.
1398+ *
1399+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1400+ */
1401+ private DataFlow:: TypeTrackingNode startResponse ( DataFlow:: TypeTracker t ) {
1402+ t .start ( ) and
1403+ exists ( WsgirefSimpleServerApplication func |
1404+ if func .isMethod ( )
1405+ then result .( DataFlow:: ParameterNode ) .getParameter ( ) = func .getArg ( 2 )
1406+ else result .( DataFlow:: ParameterNode ) .getParameter ( ) = func .getArg ( 1 )
1407+ )
1408+ or
1409+ exists ( DataFlow:: TypeTracker t2 | result = startResponse ( t2 ) .track ( t2 , t ) )
1410+ }
1411+
1412+ /**
1413+ * Gets a reference to the parameter of a `WsgirefSimpleServerApplication` that
1414+ * takes the `start_response` function.
1415+ *
1416+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1417+ */
1418+ DataFlow:: Node startResponse ( ) { startResponse ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
1419+
1420+ /**
1421+ * Gets a reference to the `write` function (that will write data to the response),
1422+ * which is the return value from calling the `start_response` function.
1423+ *
1424+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1425+ */
1426+ private DataFlow:: TypeTrackingNode writeFunction ( DataFlow:: TypeTracker t ) {
1427+ t .start ( ) and
1428+ result .( DataFlow:: CallCfgNode ) .getFunction ( ) = startResponse ( )
1429+ or
1430+ exists ( DataFlow:: TypeTracker t2 | result = writeFunction ( t2 ) .track ( t2 , t ) )
1431+ }
1432+
1433+ /**
1434+ * Gets a reference to the `write` function (that will write data to the response),
1435+ * which is the return value from calling the `start_response` function.
1436+ *
1437+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L225-L252
1438+ */
1439+ DataFlow:: Node writeFunction ( ) { writeFunction ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
1440+
1441+ /**
1442+ * A call to the `write` function.
1443+ *
1444+ * See https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/wsgiref/handlers.py#L276
1445+ */
1446+ class WsgirefSimpleServerApplicationWriteCall extends HTTP:: Server:: HttpResponse:: Range ,
1447+ DataFlow:: CallCfgNode {
1448+ WsgirefSimpleServerApplicationWriteCall ( ) { this .getFunction ( ) = writeFunction ( ) }
1449+
1450+ override DataFlow:: Node getBody ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
1451+
1452+ override DataFlow:: Node getMimetypeOrContentTypeArg ( ) { none ( ) }
1453+
1454+ override string getMimetypeDefault ( ) { none ( ) }
1455+ }
1456+
1457+ /**
1458+ * A return from a `WsgirefSimpleServerApplication`, which is included in the response body.
1459+ */
1460+ class WsgirefSimpleServerApplicationReturn extends HTTP:: Server:: HttpResponse:: Range ,
1461+ DataFlow:: CfgNode {
1462+ WsgirefSimpleServerApplicationReturn ( ) {
1463+ exists ( WsgirefSimpleServerApplication requestHandler |
1464+ node = requestHandler .getAReturnValueFlowNode ( )
1465+ )
1466+ }
1467+
1468+ override DataFlow:: Node getBody ( ) { result = this }
1469+
1470+ override DataFlow:: Node getMimetypeOrContentTypeArg ( ) { none ( ) }
1471+
1472+ override string getMimetypeDefault ( ) { none ( ) }
1473+ }
1474+ }
1475+
13191476 // ---------------------------------------------------------------------------
13201477 // sqlite3
13211478 // ---------------------------------------------------------------------------
0 commit comments