Python: Model return from flask handler as HTTP response

When dealing with

```
resp = make_response(...)
return resp
```

ideally we don't want to mark the return as a creation of a HTTP response. I'll
deal with this in a second commit, to show off how annoying it looks in the
tests right now :D
This commit is contained in:
Rasmus Wriedt Larsen
2020-10-22 14:54:58 +02:00
parent 44ba3469db
commit d60221b168
5 changed files with 75 additions and 12 deletions

View File

@@ -479,4 +479,19 @@ private module FlaskModel {
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
}
private class FlaskRouteHandlerReturn extends HTTP::Server::HttpResponse::Range, DataFlow::CfgNode {
FlaskRouteHandlerReturn() {
exists(Function routeHandler |
routeHandler = any(FlaskRouteSetup rs).getARouteHandler() and
node = routeHandler.getAReturnValueFlowNode()
)
}
override DataFlow::Node getBody() { result = this }
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
override string getMimetypeDefault() { result = "text/html" }
}
}

View File

@@ -0,0 +1,48 @@
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: HttpResponse= |
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: mimetype=text/html |
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: responseBody=response |
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |

View File

@@ -5,7 +5,7 @@ app = Flask(__name__)
@app.route("/") # $routeSetup="/"
def hello_world(): # $routeHandler
return "Hello World!"
return "Hello World!" # $HttpResponse
from flask.views import MethodView
@@ -26,14 +26,14 @@ app.add_url_rule('/the/', defaults={'user_id': None}, # $routeSetup="/the/"
@app.route("/dangerous") # $routeSetup="/dangerous"
def dangerous(): # $routeHandler
return request.args.get('payload')
return request.args.get('payload') # $HttpResponse
@app.route("/dangerous-with-cfg-split") # $routeSetup="/dangerous-with-cfg-split"
def dangerous2(): # $routeHandler
x = request.form['param0']
if request.method == "POST":
return request.form['param1']
return None
return request.form['param1'] # $HttpResponse
return None # $f+:HttpResponse
@app.route("/unsafe") # $routeSetup="/unsafe"
def unsafe(): # $routeHandler

View File

@@ -7,7 +7,7 @@ app = Flask(__name__)
@app.route("/html1") # $routeSetup="/html1"
def html1(): # $routeHandler
return "<h1>hello</h1>" # $f-:HttpResponse $f-:mimetype=text/html $f-:responseBody="<h1>hello</h1>"
return "<h1>hello</h1>" # $HttpResponse $mimetype=text/html $responseBody="<h1>hello</h1>"
@app.route("/html2") # $routeSetup="/html2"

View File

@@ -200,7 +200,7 @@ def debug(foo, bar): # $routeHandler $routedParameter=foo $routedParameter=bar
print("request.pragma {!r}".format(request.pragma))
return 'ok'
return 'ok' # $HttpResponse
@app.route("/stream", methods=['POST']) # $routeSetup="/stream"
def stream(): # $routeHandler
@@ -210,7 +210,7 @@ def stream(): # $routeHandler
# just works :)
print(s.read())
return 'ok'
return 'ok' # $HttpResponse
@app.route("/input_stream", methods=['POST']) # $routeSetup="/input_stream"
def input_stream(): # $routeHandler
@@ -221,14 +221,14 @@ def input_stream(): # $routeHandler
# be handled manually
print(s.read())
return 'ok'
return 'ok' # $HttpResponse
@app.route("/form", methods=['POST']) # $routeSetup="/form"
def form(): # $routeHandler
print(request.path)
print("request.form", request.form)
return 'ok'
return 'ok' # $HttpResponse
@app.route("/cache_control", methods=['POST']) # $routeSetup="/cache_control"
def cache_control(): # $routeHandler
@@ -237,7 +237,7 @@ def cache_control(): # $routeHandler
print("request.cache_control.max_stale", request.cache_control.max_stale, type(request.cache_control.max_stale))
print("request.cache_control.min_fresh", request.cache_control.min_fresh, type(request.cache_control.min_fresh))
return 'ok'
return 'ok' # $HttpResponse
@app.route("/file_upload", methods=['POST']) # $routeSetup="/file_upload"
def file_upload(): # $routeHandler
@@ -245,14 +245,14 @@ def file_upload(): # $routeHandler
for k,v in request.files.items():
print(k, v, v.name, v.filename, v.stream)
return 'ok'
return 'ok' # $HttpResponse
@app.route("/args", methods=['GET']) # $routeSetup="/args"
def args(): # $routeHandler
print(request.path)
print("request.args", request.args)
return 'ok'
return 'ok' # $HttpResponse
# curl --header "My-Header: some-value" http://localhost:5000/debug/fooval/barval
# curl --header "Pragma: foo, bar" --header "Pragma: stuff, foo" http://localhost:5000/debug/fooval/barval