Remove ArgumentNode assumption

This commit is contained in:
Owen Mansel-Chan
2023-04-28 05:57:09 +01:00
parent c7c0a73b90
commit 8415c4a4eb

View File

@@ -134,40 +134,44 @@ module NetHttp {
result = call.getReceiver()
}
private class ResponseBody extends Http::ResponseBody::Range, DataFlow::ArgumentNode {
private class ResponseBody extends Http::ResponseBody::Range, DataFlow::Node {
DataFlow::Node responseWriter;
ResponseBody() {
exists(DataFlow::CallNode call |
// A direct call to ResponseWriter.Write, conveying taint from the argument to the receiver
call.getTarget().(Method).implements("net/http", "ResponseWriter", "Write") and
this = call.getArgument(0) and
responseWriter = call.(DataFlow::MethodCallNode).getReceiver()
)
or
exists(TaintTracking::FunctionModel model |
// A modeled function conveying taint from some input to the response writer,
// e.g. `io.Copy(responseWriter, someTaintedReader)`
model.taintStep(this, responseWriter) and
responseWriter.getType().implements("net/http", "ResponseWriter")
)
or
exists(
SummarizedCallable callable, DataFlow::CallNode call, SummaryComponentStack input,
SummaryComponentStack output
|
callable = call.getACalleeIncludingExternals() and callable.propagatesFlow(input, output, _)
|
// A modeled function conveying taint from some input to the response writer,
// e.g. `io.Copy(responseWriter, someTaintedReader)`
// NB. SummarizedCallables do not implement a direct call-site-crossing flow step; instead
// they are implemented by a function body with internal dataflow nodes, so we mimic the
// one-step style for the particular case of taint propagation direct from an argument or receiver
// to another argument, receiver or return value, matching the behavior for a `TaintTracking::FunctionModel`.
this = getSummaryInputOrOutputNode(call, input) and
responseWriter.(DataFlow::PostUpdateNode).getPreUpdateNode() =
getSummaryInputOrOutputNode(call, output) and
responseWriter.getType().implements("net/http", "ResponseWriter")
this = any(DataFlow::CallNode call).getASyntacticArgument() and
(
exists(DataFlow::CallNode call |
// A direct call to ResponseWriter.Write, conveying taint from the argument to the receiver
call.getTarget().(Method).implements("net/http", "ResponseWriter", "Write") and
this = call.getArgument(0) and
responseWriter = call.(DataFlow::MethodCallNode).getReceiver()
)
or
exists(TaintTracking::FunctionModel model |
// A modeled function conveying taint from some input to the response writer,
// e.g. `io.Copy(responseWriter, someTaintedReader)`
model.taintStep(this, responseWriter) and
responseWriter.getType().implements("net/http", "ResponseWriter")
)
or
exists(
SummarizedCallable callable, DataFlow::CallNode call, SummaryComponentStack input,
SummaryComponentStack output
|
callable = call.getACalleeIncludingExternals() and
callable.propagatesFlow(input, output, _)
|
// A modeled function conveying taint from some input to the response writer,
// e.g. `io.Copy(responseWriter, someTaintedReader)`
// NB. SummarizedCallables do not implement a direct call-site-crossing flow step; instead
// they are implemented by a function body with internal dataflow nodes, so we mimic the
// one-step style for the particular case of taint propagation direct from an argument or receiver
// to another argument, receiver or return value, matching the behavior for a `TaintTracking::FunctionModel`.
this = getSummaryInputOrOutputNode(call, input) and
responseWriter.(DataFlow::PostUpdateNode).getPreUpdateNode() =
getSummaryInputOrOutputNode(call, output) and
responseWriter.getType().implements("net/http", "ResponseWriter")
)
)
}