From 0fe7050e7e843c5edfdf9d9364db30c7e8ec02e8 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Wed, 27 Jan 2021 17:24:46 +0100 Subject: [PATCH] Add models for HTTP::ResponseBody --- ql/src/semmle/go/frameworks/CleverGo.qll | 89 ++++++ .../frameworks/CleverGo/HttpRedirect/Test.ql | 12 +- .../Model-HttpResponseBody.go | 106 +++++++ .../CleverGo/HttpResponseBody/Test.expected | 0 .../CleverGo/HttpResponseBody/Test.ql | 23 ++ .../CleverGo/HttpResponseBody/go.mod | 5 + .../vendor/clevergo.tech/clevergo/stub.go | 270 ++++++++++++++++++ .../HttpResponseBody/vendor/modules.txt | 3 + 8 files changed, 502 insertions(+), 6 deletions(-) create mode 100644 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Model-HttpResponseBody.go create mode 100644 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.expected create mode 100644 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.ql create mode 100755 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/go.mod create mode 100644 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/clevergo.tech/clevergo/stub.go create mode 100644 ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/modules.txt diff --git a/ql/src/semmle/go/frameworks/CleverGo.qll b/ql/src/semmle/go/frameworks/CleverGo.qll index 738b1e2cf36..a04b0feb9fb 100644 --- a/ql/src/semmle/go/frameworks/CleverGo.qll +++ b/ql/src/semmle/go/frameworks/CleverGo.qll @@ -172,4 +172,93 @@ private module CleverGo { override HTTP::ResponseWriter getResponseWriter() { none() } } + + // Models HTTP ResponseBody. + private class HttpResponseBody extends HTTP::ResponseBody::Range { + string package; + DataFlow::CallNode call; + string contentType; + + HttpResponseBody() { + // HTTP ResponseBody models for package: clevergo.tech/clevergo@v0.5.2 + package = packagePath() and + // Receiver type: Context + ( + // signature: func (*Context).Error(code int, msg string) error + call = any(Method m | m.hasQualifiedName(package, "Context", "Error")).getACall() and + this = call.getArgument(1) and + contentType = "text/plain" + or + // signature: func (*Context).HTML(code int, html string) error + call = any(Method m | m.hasQualifiedName(package, "Context", "HTML")).getACall() and + this = call.getArgument(1) and + contentType = "text/html" + or + // signature: func (*Context).HTMLBlob(code int, bs []byte) error + call = any(Method m | m.hasQualifiedName(package, "Context", "HTMLBlob")).getACall() and + this = call.getArgument(1) and + contentType = "text/html" + or + // signature: func (*Context).JSON(code int, data interface{}) error + call = any(Method m | m.hasQualifiedName(package, "Context", "JSON")).getACall() and + this = call.getArgument(1) and + contentType = "application/json" + or + // signature: func (*Context).JSONBlob(code int, bs []byte) error + call = any(Method m | m.hasQualifiedName(package, "Context", "JSONBlob")).getACall() and + this = call.getArgument(1) and + contentType = "application/json" + or + // signature: func (*Context).JSONP(code int, data interface{}) error + call = any(Method m | m.hasQualifiedName(package, "Context", "JSONP")).getACall() and + this = call.getArgument(1) and + contentType = "application/javascript" + or + // signature: func (*Context).JSONPBlob(code int, bs []byte) error + call = any(Method m | m.hasQualifiedName(package, "Context", "JSONPBlob")).getACall() and + this = call.getArgument(1) and + contentType = "application/javascript" + or + // signature: func (*Context).JSONPCallback(code int, callback string, data interface{}) error + call = any(Method m | m.hasQualifiedName(package, "Context", "JSONPCallback")).getACall() and + this = call.getArgument(2) and + contentType = "application/javascript" + or + // signature: func (*Context).JSONPCallbackBlob(code int, callback string, bs []byte) (err error) + call = + any(Method m | m.hasQualifiedName(package, "Context", "JSONPCallbackBlob")).getACall() and + this = call.getArgument(2) and + contentType = "application/javascript" + or + // signature: func (*Context).String(code int, s string) error + call = any(Method m | m.hasQualifiedName(package, "Context", "String")).getACall() and + this = call.getArgument(1) and + contentType = "text/plain" + or + // signature: func (*Context).StringBlob(code int, bs []byte) error + call = any(Method m | m.hasQualifiedName(package, "Context", "StringBlob")).getACall() and + this = call.getArgument(1) and + contentType = "text/plain" + or + // signature: func (*Context).Stringf(code int, format string, a ...interface{}) error + call = any(Method m | m.hasQualifiedName(package, "Context", "Stringf")).getACall() and + this = call.getArgument([1, any(int i | i >= 2)]) and + contentType = "text/plain" + or + // signature: func (*Context).XML(code int, data interface{}) error + call = any(Method m | m.hasQualifiedName(package, "Context", "XML")).getACall() and + this = call.getArgument(1) and + contentType = "text/xml" + or + // signature: func (*Context).XMLBlob(code int, bs []byte) error + call = any(Method m | m.hasQualifiedName(package, "Context", "XMLBlob")).getACall() and + this = call.getArgument(1) and + contentType = "text/xml" + ) + } + + override string getAContentType() { result = contentType } + + override HTTP::ResponseWriter getResponseWriter() { none() } + } } diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpRedirect/Test.ql b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpRedirect/Test.ql index 5add28b156c..28420bc9dcb 100644 --- a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpRedirect/Test.ql +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpRedirect/Test.ql @@ -1,17 +1,17 @@ import go import TestUtilities.InlineExpectationsTest -class TaintTrackingTest extends InlineExpectationsTest { - TaintTrackingTest() { this = "TaintTrackingTest" } +class HttpRedirectTest extends InlineExpectationsTest { + HttpRedirectTest() { this = "HttpRedirectTest" } override string getARelevantTag() { result = "redirectUrl" } override predicate hasActualResult(string file, int line, string element, string tag, string value) { tag = "redirectUrl" and - exists(HTTP::Redirect q | - q.hasLocationInfo(file, line, _, _, _) and - element = q.getUrl().toString() and - value = q.getUrl().toString() + exists(HTTP::Redirect rd | + rd.hasLocationInfo(file, line, _, _, _) and + element = rd.getUrl().toString() and + value = rd.getUrl().toString() ) } } diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Model-HttpResponseBody.go b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Model-HttpResponseBody.go new file mode 100644 index 00000000000..6c3c310d029 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Model-HttpResponseBody.go @@ -0,0 +1,106 @@ +// Code generated by https://github.com/gagliardetto. DO NOT EDIT. + +//go:generate depstubber --vendor --auto +package main + +import "clevergo.tech/clevergo" + +func main() {} +func source() interface{} { + return nil +} + +// Package clevergo.tech/clevergo@v0.5.2 +func ClevergoTechClevergov052() { + // Set ResponseBody via method calls. + { + // Set ResponseBody via method calls on clevergo.tech/clevergo.Context. + { + // func (*Context).Error(code int, msg string) error + { + bodyString707 := source().(string) + var rece clevergo.Context + rece.Error(0, bodyString707) // $contentType=text/plain $responseBody=bodyString707 + } + // func (*Context).HTML(code int, html string) error + { + bodyString912 := source().(string) + var rece clevergo.Context + rece.HTML(0, bodyString912) // $contentType=text/html $responseBody=bodyString912 + } + // func (*Context).HTMLBlob(code int, bs []byte) error + { + bodyByte718 := source().([]byte) + var rece clevergo.Context + rece.HTMLBlob(0, bodyByte718) // $contentType=text/html $responseBody=bodyByte718 + } + // func (*Context).JSON(code int, data interface{}) error + { + bodyInterface972 := source().(interface{}) + var rece clevergo.Context + rece.JSON(0, bodyInterface972) // $contentType=application/json $responseBody=bodyInterface972 + } + // func (*Context).JSONBlob(code int, bs []byte) error + { + bodyByte633 := source().([]byte) + var rece clevergo.Context + rece.JSONBlob(0, bodyByte633) // $contentType=application/json $responseBody=bodyByte633 + } + // func (*Context).JSONP(code int, data interface{}) error + { + bodyInterface316 := source().(interface{}) + var rece clevergo.Context + rece.JSONP(0, bodyInterface316) // $contentType=application/javascript $responseBody=bodyInterface316 + } + // func (*Context).JSONPBlob(code int, bs []byte) error + { + bodyByte145 := source().([]byte) + var rece clevergo.Context + rece.JSONPBlob(0, bodyByte145) // $contentType=application/javascript $responseBody=bodyByte145 + } + // func (*Context).JSONPCallback(code int, callback string, data interface{}) error + { + bodyInterface817 := source().(interface{}) + var rece clevergo.Context + rece.JSONPCallback(0, "", bodyInterface817) // $contentType=application/javascript $responseBody=bodyInterface817 + } + // func (*Context).JSONPCallbackBlob(code int, callback string, bs []byte) (err error) + { + bodyByte474 := source().([]byte) + var rece clevergo.Context + rece.JSONPCallbackBlob(0, "", bodyByte474) // $contentType=application/javascript $responseBody=bodyByte474 + } + // func (*Context).String(code int, s string) error + { + bodyString832 := source().(string) + var rece clevergo.Context + rece.String(0, bodyString832) // $contentType=text/plain $responseBody=bodyString832 + } + // func (*Context).StringBlob(code int, bs []byte) error + { + bodyByte378 := source().([]byte) + var rece clevergo.Context + rece.StringBlob(0, bodyByte378) // $contentType=text/plain $responseBody=bodyByte378 + } + // func (*Context).Stringf(code int, format string, a ...interface{}) error + { + bodyString541 := source().(string) + bodyInterface139 := source().(interface{}) + var rece clevergo.Context + rece.Stringf(0, bodyString541, bodyInterface139) // $contentType=text/plain $responseBody=bodyString541 $responseBody=bodyInterface139 + } + // func (*Context).XML(code int, data interface{}) error + { + bodyInterface814 := source().(interface{}) + var rece clevergo.Context + rece.XML(0, bodyInterface814) // $contentType=text/xml $responseBody=bodyInterface814 + } + // func (*Context).XMLBlob(code int, bs []byte) error + { + bodyByte768 := source().([]byte) + var rece clevergo.Context + rece.XMLBlob(0, bodyByte768) // $contentType=text/xml $responseBody=bodyByte768 + } + } + } +} diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.expected b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.ql b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.ql new file mode 100644 index 00000000000..910b2965cfe --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/Test.ql @@ -0,0 +1,23 @@ +import go +import TestUtilities.InlineExpectationsTest + +class HttpResponseBodyTest extends InlineExpectationsTest { + HttpResponseBodyTest() { this = "HttpResponseBodyTest" } + + override string getARelevantTag() { result = ["contentType", "responseBody"] } + + override predicate hasActualResult(string file, int line, string element, string tag, string value) { + exists(HTTP::ResponseBody rd | + rd.hasLocationInfo(file, line, _, _, _) and + ( + element = rd.getAContentType().toString() and + value = rd.getAContentType().toString() and + tag = "contentType" + or + element = rd.toString() and + value = rd.toString() and + tag = "responseBody" + ) + ) + } +} diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/go.mod b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/go.mod new file mode 100755 index 00000000000..7a4c43477b6 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/go.mod @@ -0,0 +1,5 @@ +module example.com/hello/world + +go 1.15 + +require clevergo.tech/clevergo v0.5.2 diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/clevergo.tech/clevergo/stub.go b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/clevergo.tech/clevergo/stub.go new file mode 100644 index 00000000000..bdf8de73092 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/clevergo.tech/clevergo/stub.go @@ -0,0 +1,270 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for clevergo.tech/clevergo, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: clevergo.tech/clevergo (exports: Context; functions: ) + +// Package clevergo is a stub of clevergo.tech/clevergo, generated by depstubber. +package clevergo + +import ( + context "context" + io "io" + http "net/http" + url "net/url" + time "time" +) + +type Context struct { + Params Params + Route *Route + Request *http.Request + Response http.ResponseWriter +} + +func (_ *Context) BasicAuth() (string, string, bool) { + return "", "", false +} + +func (_ *Context) Blob(_ int, _ string, _ []byte) error { + return nil +} + +func (_ *Context) Context() context.Context { + return nil +} + +func (_ *Context) Cookie(_ string) (*http.Cookie, error) { + return nil, nil +} + +func (_ *Context) Cookies() []*http.Cookie { + return nil +} + +func (_ *Context) Decode(_ interface{}) error { + return nil +} + +func (_ *Context) DefaultQuery(_ string, _ string) string { + return "" +} + +func (_ *Context) Emit(_ int, _ string, _ string) error { + return nil +} + +func (_ *Context) Error(_ int, _ string) error { + return nil +} + +func (_ *Context) FormValue(_ string) string { + return "" +} + +func (_ *Context) GetHeader(_ string) string { + return "" +} + +func (_ *Context) HTML(_ int, _ string) error { + return nil +} + +func (_ *Context) HTMLBlob(_ int, _ []byte) error { + return nil +} + +func (_ *Context) Host() string { + return "" +} + +func (_ *Context) IsAJAX() bool { + return false +} + +func (_ *Context) IsDelete() bool { + return false +} + +func (_ *Context) IsGet() bool { + return false +} + +func (_ *Context) IsMethod(_ string) bool { + return false +} + +func (_ *Context) IsOptions() bool { + return false +} + +func (_ *Context) IsPatch() bool { + return false +} + +func (_ *Context) IsPost() bool { + return false +} + +func (_ *Context) IsPut() bool { + return false +} + +func (_ *Context) JSON(_ int, _ interface{}) error { + return nil +} + +func (_ *Context) JSONBlob(_ int, _ []byte) error { + return nil +} + +func (_ *Context) JSONP(_ int, _ interface{}) error { + return nil +} + +func (_ *Context) JSONPBlob(_ int, _ []byte) error { + return nil +} + +func (_ *Context) JSONPCallback(_ int, _ string, _ interface{}) error { + return nil +} + +func (_ *Context) JSONPCallbackBlob(_ int, _ string, _ []byte) error { + return nil +} + +func (_ *Context) Logger() interface{} { + return nil +} + +func (_ *Context) NotFound() error { + return nil +} + +func (_ *Context) PostFormValue(_ string) string { + return "" +} + +func (_ *Context) QueryParam(_ string) string { + return "" +} + +func (_ *Context) QueryParams() url.Values { + return nil +} + +func (_ *Context) QueryString() string { + return "" +} + +func (_ *Context) Redirect(_ int, _ string) error { + return nil +} + +func (_ *Context) Render(_ int, _ string, _ interface{}) error { + return nil +} + +func (_ *Context) RouteURL(_ string, _ ...string) (*url.URL, error) { + return nil, nil +} + +func (_ *Context) SendFile(_ string, _ io.Reader) error { + return nil +} + +func (_ *Context) ServeContent(_ string, _ time.Time, _ io.ReadSeeker) error { + return nil +} + +func (_ *Context) ServeFile(_ string) error { + return nil +} + +func (_ *Context) SetContentType(_ string) {} + +func (_ *Context) SetContentTypeHTML() {} + +func (_ *Context) SetContentTypeJSON() {} + +func (_ *Context) SetContentTypeText() {} + +func (_ *Context) SetContentTypeXML() {} + +func (_ *Context) SetCookie(_ *http.Cookie) {} + +func (_ *Context) SetHeader(_ string, _ string) {} + +func (_ *Context) String(_ int, _ string) error { + return nil +} + +func (_ *Context) StringBlob(_ int, _ []byte) error { + return nil +} + +func (_ *Context) Stringf(_ int, _ string, _ ...interface{}) error { + return nil +} + +func (_ *Context) Value(_ interface{}) interface{} { + return nil +} + +func (_ *Context) WithValue(_ interface{}, _ interface{}) {} + +func (_ *Context) Write(_ []byte) (int, error) { + return 0, nil +} + +func (_ *Context) WriteHeader(_ int) {} + +func (_ *Context) WriteString(_ string) (int, error) { + return 0, nil +} + +func (_ *Context) XML(_ int, _ interface{}) error { + return nil +} + +func (_ *Context) XMLBlob(_ int, _ []byte) error { + return nil +} + +type Param struct { + Key string + Value string +} + +type Params []Param + +func (_ Params) Bool(_ string) (bool, error) { + return false, nil +} + +func (_ Params) Float64(_ string) (float64, error) { + return 0, nil +} + +func (_ Params) Int(_ string) (int, error) { + return 0, nil +} + +func (_ Params) Int64(_ string) (int64, error) { + return 0, nil +} + +func (_ Params) String(_ string) string { + return "" +} + +func (_ Params) Uint64(_ string) (uint64, error) { + return 0, nil +} + +type Route struct{} + +func (_ *Route) URL(_ ...string) (*url.URL, error) { + return nil, nil +} diff --git a/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/modules.txt b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/modules.txt new file mode 100644 index 00000000000..6a030c729e1 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/CleverGo/HttpResponseBody/vendor/modules.txt @@ -0,0 +1,3 @@ +# clevergo.tech/clevergo v0.5.2 +## explicit +clevergo.tech/clevergo