@@ -2183,17 +2183,35 @@ module StdlibPrivate {
21832183 * for how a request is processed and given to an application.
21842184 */
21852185 class WsgirefSimpleServerApplication extends Http:: Server:: RequestHandler:: Range {
2186+ boolean validator ;
2187+
21862188 WsgirefSimpleServerApplication ( ) {
21872189 exists ( DataFlow:: Node appArg , DataFlow:: CallCfgNode setAppCall |
21882190 (
21892191 setAppCall =
2190- WsgirefSimpleServer:: subclassRef ( ) .getReturn ( ) .getMember ( "set_app" ) .getACall ( )
2192+ WsgirefSimpleServer:: subclassRef ( ) .getReturn ( ) .getMember ( "set_app" ) .getACall ( ) and
2193+ validator = false
21912194 or
21922195 setAppCall
21932196 .( 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
21952204 ) and
21962205 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
21972215 |
21982216 appArg = poorMansFunctionTracker ( this )
21992217 )
@@ -2202,6 +2220,9 @@ module StdlibPrivate {
22022220 override Parameter getARoutedParameter ( ) { none ( ) }
22032221
22042222 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 }
22052226 }
22062227
22072228 /**
@@ -2305,6 +2326,114 @@ module StdlibPrivate {
23052326
23062327 override string getMimetypeDefault ( ) { none ( ) }
23072328 }
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+ }
23082437 }
23092438
23102439 // ---------------------------------------------------------------------------
0 commit comments