@@ -2183,17 +2183,35 @@ module StdlibPrivate {
2183
2183
* for how a request is processed and given to an application.
2184
2184
*/
2185
2185
class WsgirefSimpleServerApplication extends Http:: Server:: RequestHandler:: Range {
2186
+ boolean validator ;
2187
+
2186
2188
WsgirefSimpleServerApplication ( ) {
2187
2189
exists ( DataFlow:: Node appArg , DataFlow:: CallCfgNode setAppCall |
2188
2190
(
2189
2191
setAppCall =
2190
- WsgirefSimpleServer:: subclassRef ( ) .getReturn ( ) .getMember ( "set_app" ) .getACall ( )
2192
+ WsgirefSimpleServer:: subclassRef ( ) .getReturn ( ) .getMember ( "set_app" ) .getACall ( ) and
2193
+ validator = false
2191
2194
or
2192
2195
setAppCall
2193
2196
.( DataFlow:: MethodCallNode )
2194
- .calls ( any ( WsgiServerSubclass cls ) .getASelfRef ( ) , "set_app" )
2197
+ .calls ( any ( WsgiServerSubclass cls ) .getASelfRef ( ) , "set_app" ) and
2198
+ validator = false
2199
+ or
2200
+ // assume an application that is passed to `wsgiref.validate.validator` is eventually passed to `set_app`
2201
+ setAppCall =
2202
+ API:: moduleImport ( "wsgiref" ) .getMember ( "validate" ) .getMember ( "validator" ) .getACall ( ) and
2203
+ validator = true
2195
2204
) and
2196
2205
appArg in [ setAppCall .getArg ( 0 ) , setAppCall .getArgByName ( "application" ) ]
2206
+ or
2207
+ // `make_server` calls `set_app`
2208
+ setAppCall =
2209
+ API:: moduleImport ( "wsgiref" )
2210
+ .getMember ( "simple_server" )
2211
+ .getMember ( "make_server" )
2212
+ .getACall ( ) and
2213
+ appArg in [ setAppCall .getArg ( 2 ) , setAppCall .getArgByName ( "app" ) ] and
2214
+ validator = false
2197
2215
|
2198
2216
appArg = poorMansFunctionTracker ( this )
2199
2217
)
@@ -2202,6 +2220,9 @@ module StdlibPrivate {
2202
2220
override Parameter getARoutedParameter ( ) { none ( ) }
2203
2221
2204
2222
override string getFramework ( ) { result = "Stdlib: wsgiref.simple_server application" }
2223
+
2224
+ /** Holds if this simple server application was passed to `wsgiref.validate.validator`. */
2225
+ predicate isValidated ( ) { validator = true }
2205
2226
}
2206
2227
2207
2228
/**
@@ -2305,6 +2326,114 @@ module StdlibPrivate {
2305
2326
2306
2327
override string getMimetypeDefault ( ) { none ( ) }
2307
2328
}
2329
+
2330
+ /**
2331
+ * Provides models for the `wsgiref.headers.Headers` class
2332
+ *
2333
+ * See https://docs.python.org/3/library/wsgiref.html#module-wsgiref.headers.
2334
+ */
2335
+ module Headers {
2336
+ /** Gets a reference to the `wsgiref.headers.Headers` class. */
2337
+ API:: Node classRef ( ) {
2338
+ result = API:: moduleImport ( "wsgiref" ) .getMember ( "headers" ) .getMember ( "Headers" )
2339
+ or
2340
+ result = ModelOutput:: getATypeNode ( "wsgiref.headers.Headers~Subclass" ) .getASubclass * ( )
2341
+ }
2342
+
2343
+ /** Gets a reference to an instance of `wsgiref.headers.Headers`. */
2344
+ private DataFlow:: TypeTrackingNode instance ( DataFlow:: TypeTracker t ) {
2345
+ t .start ( ) and
2346
+ result = classRef ( ) .getACall ( )
2347
+ or
2348
+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
2349
+ }
2350
+
2351
+ /** Gets a reference to an instance of `wsgiref.headers.Headers`. */
2352
+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
2353
+
2354
+ /** Holds if there exists an application that is validated by `wsgiref.validate.validator`. */
2355
+ private predicate existsValidatedApplication ( ) {
2356
+ exists ( WsgirefSimpleServerApplication app | app .isValidated ( ) )
2357
+ }
2358
+
2359
+ /** A class instantiation of `wsgiref.headers.Headers`, conidered as a write to a response header. */
2360
+ private class WsgirefHeadersInstantiation extends Http:: Server:: ResponseHeaderBulkWrite:: Range ,
2361
+ DataFlow:: CallCfgNode
2362
+ {
2363
+ WsgirefHeadersInstantiation ( ) { this = classRef ( ) .getACall ( ) }
2364
+
2365
+ override DataFlow:: Node getBulkArg ( ) {
2366
+ result = [ this .getArg ( 0 ) , this .getArgByName ( "headers" ) ]
2367
+ }
2368
+
2369
+ // TODO: These checks perhaps could be made more precise.
2370
+ override predicate nameAllowsNewline ( ) { not existsValidatedApplication ( ) }
2371
+
2372
+ override predicate valueAllowsNewline ( ) { not existsValidatedApplication ( ) }
2373
+ }
2374
+
2375
+ /** A call to a method that writes to a response header. */
2376
+ private class HeaderWriteCall extends Http:: Server:: ResponseHeaderWrite:: Range ,
2377
+ DataFlow:: MethodCallNode
2378
+ {
2379
+ HeaderWriteCall ( ) {
2380
+ this .calls ( instance ( ) , [ "add_header" , "set" , "setdefault" , "__setitem__" ] )
2381
+ }
2382
+
2383
+ override DataFlow:: Node getNameArg ( ) { result = this .getArg ( 0 ) }
2384
+
2385
+ override DataFlow:: Node getValueArg ( ) { result = this .getArg ( 1 ) }
2386
+
2387
+ // TODO: These checks perhaps could be made more precise.
2388
+ override predicate nameAllowsNewline ( ) { not existsValidatedApplication ( ) }
2389
+
2390
+ override predicate valueAllowsNewline ( ) { not existsValidatedApplication ( ) }
2391
+ }
2392
+
2393
+ /** A dict-like write to a response header. */
2394
+ private class HeaderWriteSubscript extends Http:: Server:: ResponseHeaderWrite:: Range ,
2395
+ DataFlow:: Node
2396
+ {
2397
+ DataFlow:: Node name ;
2398
+ DataFlow:: Node value ;
2399
+
2400
+ HeaderWriteSubscript ( ) {
2401
+ exists ( SubscriptNode subscript |
2402
+ this .asCfgNode ( ) = subscript and
2403
+ value .asCfgNode ( ) = subscript .( DefinitionNode ) .getValue ( ) and
2404
+ name .asCfgNode ( ) = subscript .getIndex ( ) and
2405
+ subscript .getObject ( ) = instance ( ) .asCfgNode ( )
2406
+ )
2407
+ }
2408
+
2409
+ override DataFlow:: Node getNameArg ( ) { result = name }
2410
+
2411
+ override DataFlow:: Node getValueArg ( ) { result = value }
2412
+
2413
+ // TODO: These checks perhaps could be made more precise.
2414
+ override predicate nameAllowsNewline ( ) { not existsValidatedApplication ( ) }
2415
+
2416
+ override predicate valueAllowsNewline ( ) { not existsValidatedApplication ( ) }
2417
+ }
2418
+
2419
+ /**
2420
+ * A call to a `start_response` function that sets the response headers.
2421
+ */
2422
+ private class WsgirefSimpleServerSetHeaders extends Http:: Server:: ResponseHeaderBulkWrite:: Range ,
2423
+ DataFlow:: CallCfgNode
2424
+ {
2425
+ WsgirefSimpleServerSetHeaders ( ) { this .getFunction ( ) = startResponse ( ) }
2426
+
2427
+ override DataFlow:: Node getBulkArg ( ) {
2428
+ result = [ this .getArg ( 1 ) , this .getArgByName ( "headers" ) ]
2429
+ }
2430
+
2431
+ // TODO: These checks perhaps could be made more precise.
2432
+ override predicate nameAllowsNewline ( ) { not existsValidatedApplication ( ) }
2433
+
2434
+ override predicate valueAllowsNewline ( ) { not existsValidatedApplication ( ) }
2435
+ }
2436
+ }
2308
2437
}
2309
2438
2310
2439
// ---------------------------------------------------------------------------
0 commit comments