Stub alternative HTTP::ResponseBody model implementation

This commit is contained in:
Slavomir
2021-04-12 23:37:22 +02:00
committed by Chris Smowton
parent ff848a502a
commit 78b403f42e
2 changed files with 234 additions and 152 deletions

View File

@@ -198,168 +198,249 @@ private module CleverGo {
/**
* Models HTTP ResponseBody.
*/
private class HttpResponseBody extends HTTP::ResponseBody::Range {
string package;
DataFlow::CallNode bodySetterCall;
string contentType;
private class HttpResponseBodyContentTypeString extends HTTP::ResponseBody::Range {
string contentTypeString;
HttpResponseBody() {
// HTTP ResponseBody models for package: clevergo.tech/clevergo@v0.5.2
package = packagePath() and
(
// One call sets both body and content-type (which is implicit in the func name).
// Receiver type: Context
exists(string methodName, Method m |
m.hasQualifiedName(package, "Context", methodName) and
bodySetterCall = m.getACall()
|
// signature: func (*Context).Error(code int, msg string) error
methodName = "Error" and
this = bodySetterCall.getArgument(1) and
contentType = "text/plain"
or
// signature: func (*Context).HTML(code int, html string) error
methodName = "HTML" and
this = bodySetterCall.getArgument(1) and
contentType = "text/html"
or
// signature: func (*Context).HTMLBlob(code int, bs []byte) error
methodName = "HTMLBlob" and
this = bodySetterCall.getArgument(1) and
contentType = "text/html"
or
// signature: func (*Context).JSON(code int, data interface{}) error
methodName = "JSON" and
this = bodySetterCall.getArgument(1) and
contentType = "application/json"
or
// signature: func (*Context).JSONBlob(code int, bs []byte) error
methodName = "JSONBlob" and
this = bodySetterCall.getArgument(1) and
contentType = "application/json"
or
// signature: func (*Context).JSONP(code int, data interface{}) error
methodName = "JSONP" and
this = bodySetterCall.getArgument(1) and
contentType = "application/javascript"
or
// signature: func (*Context).JSONPBlob(code int, bs []byte) error
methodName = "JSONPBlob" and
this = bodySetterCall.getArgument(1) and
contentType = "application/javascript"
or
// signature: func (*Context).JSONPCallback(code int, callback string, data interface{}) error
methodName = "JSONPCallback" and
this = bodySetterCall.getArgument(2) and
contentType = "application/javascript"
or
// signature: func (*Context).JSONPCallbackBlob(code int, callback string, bs []byte) (err error)
methodName = "JSONPCallbackBlob" and
this = bodySetterCall.getArgument(2) and
contentType = "application/javascript"
or
// signature: func (*Context).String(code int, s string) error
methodName = "String" and
this = bodySetterCall.getArgument(1) and
contentType = "text/plain"
or
// signature: func (*Context).StringBlob(code int, bs []byte) error
methodName = "StringBlob" and
this = bodySetterCall.getArgument(1) and
contentType = "text/plain"
or
// signature: func (*Context).Stringf(code int, format string, a ...interface{}) error
methodName = "Stringf" and
this = bodySetterCall.getArgument([1, any(int i | i >= 2)]) and
contentType = "text/plain"
or
// signature: func (*Context).XML(code int, data interface{}) error
methodName = "XML" and
this = bodySetterCall.getArgument(1) and
contentType = "text/xml"
or
// signature: func (*Context).XMLBlob(code int, bs []byte) error
methodName = "XMLBlob" and
this = bodySetterCall.getArgument(1) and
contentType = "text/xml"
)
HttpResponseBodyContentTypeString() {
exists(string package, string receiverName |
holdsBodyAndContentTypeString(package, receiverName, this, contentTypeString)
or
// One call sets both body and content-type (both are parameters in the func call).
// Receiver type: Context
exists(string methodName, Method m |
m.hasQualifiedName(package, "Context", methodName) and
bodySetterCall = m.getACall()
exists(DataFlow::CallNode bodySetterCall, DataFlow::CallNode contentTypeSetterCall |
holdsBodyOnly(package, receiverName, bodySetterCall, this) and
holdsContentTypeString(package, receiverName, contentTypeSetterCall, contentTypeString)
|
// signature: func (*Context).Blob(code int, contentType string, bs []byte) (err error)
methodName = "Blob" and
this = bodySetterCall.getArgument(2) and
contentType = bodySetterCall.getArgument(1).getAPredecessor*().getStringValue()
or
// signature: func (*Context).Emit(code int, contentType string, body string) (err error)
methodName = "Emit" and
this = bodySetterCall.getArgument(2) and
contentType = bodySetterCall.getArgument(1).getAPredecessor*().getStringValue()
)
or
// Two calls, one to set the response body and one to set the content-type.
// Receiver type: Context
exists(string methodName, Method m |
m.hasQualifiedName(package, "Context", methodName) and
bodySetterCall = m.getACall()
|
// signature: func (*Context).Write(data []byte) (int, error)
methodName = "Write" and
this = bodySetterCall.getArgument(0)
or
// signature: func (*Context).WriteString(data string) (int, error)
methodName = "WriteString" and
this = bodySetterCall.getArgument(0)
) and
(
// Receiver type: Context
exists(string methodName, Method m, DataFlow::CallNode contentTypeSetterCall |
m.hasQualifiedName(package, "Context", methodName) and
contentTypeSetterCall = m.getACall() and
contentTypeSetterCall.getReceiver().getAPredecessor*() =
bodySetterCall.getReceiver().getAPredecessor*()
|
// signature: func (*Context).SetContentType(v string)
methodName = "SetContentType" and
contentType = contentTypeSetterCall.getArgument(0).getAPredecessor*().getStringValue()
)
or
// Receiver type: Context
exists(string methodName, Method m, DataFlow::CallNode contentTypeSetterCall |
m.hasQualifiedName(package, "Context", methodName) and
contentTypeSetterCall = m.getACall() and
contentTypeSetterCall.getReceiver().getAPredecessor*() =
bodySetterCall.getReceiver().getAPredecessor*()
|
// signature: func (*Context).SetContentTypeHTML()
methodName = "SetContentTypeHTML" and
contentType = "text/html"
or
// signature: func (*Context).SetContentTypeJSON()
methodName = "SetContentTypeJSON" and
contentType = "application/json"
or
// signature: func (*Context).SetContentTypeText()
methodName = "SetContentTypeText" and
contentType = "text/plain"
or
// signature: func (*Context).SetContentTypeXML()
methodName = "SetContentTypeXML" and
contentType = "text/xml"
)
contentTypeSetterCall.getReceiver().getAPredecessor*() =
bodySetterCall.getReceiver().getAPredecessor*()
)
)
}
override string getAContentType() { result = contentType }
override string getAContentType() { result = contentTypeString }
override HTTP::ResponseWriter getResponseWriter() { none() }
}
/**
* Models HTTP ResponseBody.
*/
private class HttpResponseBodyContentTypeNode extends HTTP::ResponseBody::Range {
DataFlow::Node contentTypeNode;
HttpResponseBodyContentTypeNode() {
exists(string package, string receiverName |
holdsBodyAndContentTypeNode(package, receiverName, this, contentTypeNode)
or
exists(DataFlow::CallNode bodySetterCall, DataFlow::CallNode contentTypeSetterCall |
holdsBodyOnly(package, receiverName, bodySetterCall, this) and
holdsContentTypeNode(package, receiverName, contentTypeSetterCall, contentTypeNode)
|
contentTypeSetterCall.getReceiver().getAPredecessor*() =
bodySetterCall.getReceiver().getAPredecessor*()
)
)
}
override DataFlow::Node getAContentTypeNode() { result = contentTypeNode.getAPredecessor*() }
override HTTP::ResponseWriter getResponseWriter() { none() }
}
// Holds for a call that sets the body.
private predicate holdsBodyOnly(
string package, string receiverName, DataFlow::CallNode bodySetterCall, DataFlow::Node bodyNode
) {
exists(string methodName, Method m |
m.hasQualifiedName(package, receiverName, methodName) and
bodySetterCall = m.getACall()
|
package = packagePath() and
(
// Receiver type: Context
receiverName = "Context" and
(
// signature: func (*Context).Write(data []byte) (int, error)
methodName = "Write" and
bodyNode = bodySetterCall.getArgument(0)
or
// signature: func (*Context).WriteString(data string) (int, error)
methodName = "WriteString" and
bodyNode = bodySetterCall.getArgument(0)
)
)
)
}
// Holds for a call that sets the body; the content-type is implicit.
private predicate holdsBodyAndContentTypeString(
string package, string receiverName, DataFlow::Node bodyNode, string contentTypeString
) {
// One call sets both body and content-type (which is implicit in the func name).
exists(string methodName, Method m, DataFlow::CallNode bodySetterCall |
m.hasQualifiedName(package, receiverName, methodName) and
bodySetterCall = m.getACall()
|
package = packagePath() and
(
// Receiver type: Context
receiverName = "Context" and
(
// signature: func (*Context).Error(code int, msg string) error
methodName = "Error" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
// signature: func (*Context).HTML(code int, html string) error
methodName = "HTML" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/html"
or
// signature: func (*Context).HTMLBlob(code int, bs []byte) error
methodName = "HTMLBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/html"
or
// signature: func (*Context).JSON(code int, data interface{}) error
methodName = "JSON" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/json"
or
// signature: func (*Context).JSONBlob(code int, bs []byte) error
methodName = "JSONBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/json"
or
// signature: func (*Context).JSONP(code int, data interface{}) error
methodName = "JSONP" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/javascript"
or
// signature: func (*Context).JSONPBlob(code int, bs []byte) error
methodName = "JSONPBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/javascript"
or
// signature: func (*Context).JSONPCallback(code int, callback string, data interface{}) error
methodName = "JSONPCallback" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeString = "application/javascript"
or
// signature: func (*Context).JSONPCallbackBlob(code int, callback string, bs []byte) (err error)
methodName = "JSONPCallbackBlob" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeString = "application/javascript"
or
// signature: func (*Context).String(code int, s string) error
methodName = "String" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
// signature: func (*Context).StringBlob(code int, bs []byte) error
methodName = "StringBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
// signature: func (*Context).Stringf(code int, format string, a ...interface{}) error
methodName = "Stringf" and
bodyNode = bodySetterCall.getArgument([1, any(int i | i >= 2)]) and
contentTypeString = "text/plain"
or
// signature: func (*Context).XML(code int, data interface{}) error
methodName = "XML" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/xml"
or
// signature: func (*Context).XMLBlob(code int, bs []byte) error
methodName = "XMLBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/xml"
)
)
)
}
// Holds for a call that sets the body; the content-type is a parameter.
private predicate holdsBodyAndContentTypeNode(
string package, string receiverName, DataFlow::Node bodyNode, DataFlow::Node contentTypeNode
) {
exists(string methodName, Method m, DataFlow::CallNode bodySetterCall |
m.hasQualifiedName(package, receiverName, methodName) and
bodySetterCall = m.getACall()
|
package = packagePath() and
(
// Receiver type: Context
receiverName = "Context" and
(
// signature: func (*Context).Blob(code int, contentType string, bs []byte) (err error)
methodName = "Blob" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeNode = bodySetterCall.getArgument(1)
or
// signature: func (*Context).Emit(code int, contentType string, body string) (err error)
methodName = "Emit" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeNode = bodySetterCall.getArgument(1)
)
)
)
}
// Holds for a call that sets the content-type (implicit).
private predicate holdsContentTypeString(
string package, string receiverName, DataFlow::CallNode contentTypeSetterCall,
string contentType
) {
exists(string methodName, Method m |
m.hasQualifiedName(package, receiverName, methodName) and
contentTypeSetterCall = m.getACall()
|
package = packagePath() and
(
// Receiver type: Context
receiverName = "Context" and
(
// signature: func (*Context).SetContentTypeHTML()
methodName = "SetContentTypeHTML" and
contentType = "text/html"
or
// signature: func (*Context).SetContentTypeJSON()
methodName = "SetContentTypeJSON" and
contentType = "application/json"
or
// signature: func (*Context).SetContentTypeText()
methodName = "SetContentTypeText" and
contentType = "text/plain"
or
// signature: func (*Context).SetContentTypeXML()
methodName = "SetContentTypeXML" and
contentType = "text/xml"
)
)
)
}
// Holds for a call that sets the content-type via a parameter.
private predicate holdsContentTypeNode(
string package, string receiverName, DataFlow::CallNode contentTypeSetterCall,
DataFlow::Node contentTypeNode
) {
exists(string methodName, Method m |
m.hasQualifiedName(package, receiverName, methodName) and
contentTypeSetterCall = m.getACall()
|
package = packagePath() and
(
// Receiver type: Context
receiverName = "Context" and
(
// signature: func (*Context).SetContentType(v string)
methodName = "SetContentType" and
contentTypeNode = contentTypeSetterCall.getArgument(0)
)
)
)
}
/**
* Models a HTTP header writer model for package: clevergo.tech/clevergo@v0.5.2
*/

View File

@@ -105,7 +105,8 @@ func HttpResponseBody_ClevergoTechClevergov052() {
{
bodyByte839 := source().([]byte)
var rece clevergo.Context
rece.Blob(0, "application/json", bodyByte839) // $contentType=application/json $responseBody=bodyByte839
ct := "application/json"
rece.Blob(0, ct, bodyByte839) // $contentType=application/json $responseBody=bodyByte839
}
// func (*Context).Emit(code int, contentType string, body string) (err error)
{