@@ -10,6 +10,8 @@ private import semmle.python.dataflow.new.RemoteFlowSources
10
10
private import semmle.python.Concepts
11
11
private import semmle.python.ApiGraphs
12
12
private import semmle.python.frameworks.PEP249
13
+ private import semmle.python.frameworks.internal.PoorMansFunctionResolution
14
+ private import semmle.python.frameworks.internal.SelfRefMixin
13
15
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
14
16
15
17
/** Provides models for the Python standard library. */
@@ -1349,6 +1351,161 @@ private module StdlibPrivate {
1349
1351
}
1350
1352
}
1351
1353
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
+
1352
1509
// ---------------------------------------------------------------------------
1353
1510
// sqlite3
1354
1511
// ---------------------------------------------------------------------------
0 commit comments