Skip to content

Commit b6aaff2

Browse files
committed
use SimpleGlobal with source and sink to find BodyWriter successors globally
1 parent a3fbc3c commit b6aaff2

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

go/ql/lib/semmle/go/frameworks/Fasthttp.qll

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,34 @@ module Fasthttp {
8181
}
8282
}
8383

84+
private predicate responseBodyWriterResult(DataFlow::Node src) {
85+
exists(Method responseBodyWriter |
86+
responseBodyWriter.hasQualifiedName(packagePath(), "Response", "BodyWriter") and
87+
src = responseBodyWriter.getACall().getResult(0)
88+
)
89+
}
90+
91+
private predicate writerSinkAndBody(DataFlow::Node sink, DataFlow::Node body) {
92+
exists(DataFlow::CallNode writerCall |
93+
writerCall = any(Method write | write.hasQualifiedName("io", "Writer", "Write")).getACall() and
94+
sink = writerCall.getReceiver() and
95+
body = writerCall.getArgument(0)
96+
)
97+
or
98+
exists(DataFlow::CallNode writerCall |
99+
writerCall = any(Function fprintf | fprintf.hasQualifiedName("fmt", "Fprintf")).getACall() and
100+
sink = writerCall.getArgument(0) and
101+
body = writerCall.getSyntacticArgument(any(int i | i > 1))
102+
)
103+
}
104+
105+
private predicate writerSink(DataFlow::Node sink) { writerSinkAndBody(sink, _) }
106+
107+
private module ResponseBodyWriterFlow =
108+
DataFlow::SimpleGlobal<responseBodyWriterResult/1>::Graph<writerSink/1>;
109+
84110
private class ResponseBody extends Http::ResponseBody::Range {
85-
DataFlow::MethodCallNode call;
111+
DataFlow::MethodCallNode responseWriterMethodCall;
86112

87113
ResponseBody() {
88114
exists(Method m |
@@ -91,32 +117,24 @@ module Fasthttp {
91117
"AppendBody", "AppendBodyString", "SetBody", "SetBodyRaw", "SetBodyStream",
92118
"SetBodyString", "Success", "SuccessString"
93119
]) and
94-
call = m.getACall() and
95-
this = call.getArgument(0)
120+
responseWriterMethodCall = m.getACall() and
121+
this = responseWriterMethodCall.getArgument(0)
96122
or
97123
m.hasQualifiedName(packagePath(), "RequestCtx", ["Success", "SuccessString"]) and
98-
call = m.getACall() and
99-
this = call.getArgument(1)
100-
)
101-
or
102-
exists(Method responseBodyWriter, DataFlow::CallNode writerCall |
103-
responseBodyWriter.hasQualifiedName(packagePath(), "Response", "BodyWriter") and
104-
call = responseBodyWriter.getACall() and
105-
writerCall = any(Method write | write.hasQualifiedName("io", "Writer", "Write")).getACall() and
106-
this = writerCall.getArgument(0) and
107-
DataFlow::localFlow(call.getResult(0), writerCall.getReceiver())
124+
responseWriterMethodCall = m.getACall() and
125+
this = responseWriterMethodCall.getArgument(1)
108126
)
109127
or
110-
exists(Method responseBodyWriter, DataFlow::CallNode writerCall |
111-
responseBodyWriter.hasQualifiedName(packagePath(), "Response", "BodyWriter") and
112-
call = responseBodyWriter.getACall() and
113-
writerCall = any(Function fprintf | fprintf.hasQualifiedName("fmt", "Fprintf")).getACall() and
114-
this = writerCall.getSyntacticArgument(any(int i | i > 1)) and
115-
DataFlow::localFlow(call.getResult(0), writerCall.getArgument(0))
128+
exists(ResponseBodyWriterFlow::PathNode source, ResponseBodyWriterFlow::PathNode sink |
129+
ResponseBodyWriterFlow::flowPath(source, sink) and
130+
responseWriterMethodCall = source.getNode() and
131+
writerSinkAndBody(sink.getNode(), this)
116132
)
117133
}
118134

119-
override Http::ResponseWriter getResponseWriter() { result.getANode() = call.getReceiver() }
135+
override Http::ResponseWriter getResponseWriter() {
136+
result.getANode() = responseWriterMethodCall.getReceiver()
137+
}
120138
}
121139

122140
/**

0 commit comments

Comments
 (0)