Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 85f9760

Browse files
committed
Move existing net/http classes from private module StdlibHttp to stdlib.NetHttp
1 parent e66fcef commit 85f9760

File tree

2 files changed

+210
-228
lines changed

2 files changed

+210
-228
lines changed

ql/src/semmle/go/frameworks/HTTP.qll

Lines changed: 0 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -4,234 +4,6 @@
44

55
import go
66

7-
private module StdlibHttp {
8-
/** An access to an HTTP request field whose value may be controlled by an untrusted user. */
9-
private class UserControlledRequestField extends UntrustedFlowSource::Range,
10-
DataFlow::FieldReadNode {
11-
UserControlledRequestField() {
12-
exists(string fieldName | this.getField().hasQualifiedName("net/http", "Request", fieldName) |
13-
fieldName = "Body" or
14-
fieldName = "GetBody" or
15-
fieldName = "Form" or
16-
fieldName = "PostForm" or
17-
fieldName = "MultipartForm" or
18-
fieldName = "Header" or
19-
fieldName = "Trailer" or
20-
fieldName = "URL"
21-
)
22-
}
23-
}
24-
25-
private class UserControlledRequestMethod extends UntrustedFlowSource::Range,
26-
DataFlow::MethodCallNode {
27-
UserControlledRequestMethod() {
28-
exists(string methName | this.getTarget().hasQualifiedName("net/http", "Request", methName) |
29-
methName = "Cookie" or
30-
methName = "Cookies" or
31-
methName = "FormFile" or
32-
methName = "FormValue" or
33-
methName = "MultipartReader" or
34-
methName = "PostFormValue" or
35-
methName = "Referer" or
36-
methName = "UserAgent"
37-
)
38-
}
39-
}
40-
41-
private class HeaderGet extends TaintTracking::FunctionModel, Method {
42-
HeaderGet() { this.hasQualifiedName("net/http", "Header", "Get") }
43-
44-
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
45-
inp.isReceiver() and outp.isResult()
46-
}
47-
}
48-
49-
private class HeaderValues extends TaintTracking::FunctionModel, Method {
50-
HeaderValues() { this.hasQualifiedName("net/http", "Header", "Values") }
51-
52-
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
53-
inp.isReceiver() and outp.isResult()
54-
}
55-
}
56-
57-
/** The declaration of a variable which either is or has a field that implements the http.ResponseWriter type */
58-
private class StdlibResponseWriter extends HTTP::ResponseWriter::Range {
59-
SsaWithFields v;
60-
61-
StdlibResponseWriter() {
62-
this = v.getBaseVariable().getSourceVariable() and
63-
exists(Type t | t.implements("net/http", "ResponseWriter") | v.getType() = t)
64-
}
65-
66-
override DataFlow::Node getANode() { result = v.similar().getAUse().getASuccessor*() }
67-
68-
/** Gets a header object that corresponds to this HTTP response. */
69-
DataFlow::MethodCallNode getAHeaderObject() {
70-
result.getTarget().getName() = "Header" and
71-
this.getANode() = result.getReceiver()
72-
}
73-
}
74-
75-
private class HeaderWriteCall extends HTTP::HeaderWrite::Range, DataFlow::MethodCallNode {
76-
HeaderWriteCall() {
77-
this.getTarget().hasQualifiedName("net/http", "Header", "Add") or
78-
this.getTarget().hasQualifiedName("net/http", "Header", "Set")
79-
}
80-
81-
override DataFlow::Node getName() { result = this.getArgument(0) }
82-
83-
override DataFlow::Node getValue() { result = this.getArgument(1) }
84-
85-
override HTTP::ResponseWriter getResponseWriter() {
86-
// find `v` in
87-
// ```
88-
// header := v.Header()
89-
// header.Add(...)
90-
// ```
91-
result.(StdlibResponseWriter).getAHeaderObject().getASuccessor*() = this.getReceiver()
92-
}
93-
}
94-
95-
private class MapWrite extends HTTP::HeaderWrite::Range, DataFlow::Node {
96-
Write write;
97-
DataFlow::Node index;
98-
DataFlow::Node rhs;
99-
100-
MapWrite() {
101-
this.getType().hasQualifiedName("net/http", "Header") and
102-
write.writesElement(this, index, rhs)
103-
}
104-
105-
override DataFlow::Node getName() { result = index }
106-
107-
override DataFlow::Node getValue() { result = rhs }
108-
109-
override HTTP::ResponseWriter getResponseWriter() {
110-
// find `v` in
111-
// ```
112-
// header := v.Header()
113-
// header[...] = ...
114-
// ```
115-
result.(StdlibResponseWriter).getAHeaderObject().getASuccessor*() = this
116-
}
117-
}
118-
119-
private class ResponseWriteHeaderCall extends HTTP::HeaderWrite::Range, DataFlow::MethodCallNode {
120-
ResponseWriteHeaderCall() {
121-
this.getTarget().implements("net/http", "ResponseWriter", "WriteHeader")
122-
}
123-
124-
override string getHeaderName() { result = "status" }
125-
126-
override predicate definesHeader(string header, string value) {
127-
header = "status" and value = this.getValue().getIntValue().toString()
128-
}
129-
130-
override DataFlow::Node getName() { none() }
131-
132-
override DataFlow::Node getValue() { result = this.getArgument(0) }
133-
134-
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() }
135-
}
136-
137-
private class RequestBody extends HTTP::RequestBody::Range, DataFlow::ExprNode {
138-
RequestBody() {
139-
exists(Function newRequest |
140-
newRequest.hasQualifiedName("net/http", "NewRequest") and
141-
this = newRequest.getACall().getArgument(2)
142-
)
143-
or
144-
exists(Field body, Type request |
145-
request.hasQualifiedName("net/http", "Request") and
146-
body = request.getField("Body") and
147-
this = body.getAWrite().getRhs()
148-
)
149-
}
150-
}
151-
152-
private class ResponseBody extends HTTP::ResponseBody::Range, DataFlow::ArgumentNode {
153-
int arg;
154-
155-
ResponseBody() {
156-
exists(DataFlow::CallNode call |
157-
call.getTarget().(Method).implements("net/http", "ResponseWriter", "Write") and
158-
arg = 0
159-
or
160-
(
161-
call.getTarget().hasQualifiedName("fmt", "Fprintf")
162-
or
163-
call.getTarget().hasQualifiedName("io", "WriteString")
164-
) and
165-
call.getArgument(0).getType().hasQualifiedName("net/http", "ResponseWriter") and
166-
arg >= 1
167-
|
168-
this = call.getArgument(arg)
169-
)
170-
}
171-
172-
override HTTP::ResponseWriter getResponseWriter() {
173-
// the response writer is the receiver of this call
174-
result.getANode() = this.getCall().(DataFlow::MethodCallNode).getReceiver()
175-
or
176-
// the response writer is an argument to Fprintf or WriteString
177-
arg >= 1 and
178-
result.getANode() = this.getCall().getArgument(0)
179-
}
180-
}
181-
182-
private class RedirectCall extends HTTP::Redirect::Range, DataFlow::CallNode {
183-
RedirectCall() { this.getTarget().hasQualifiedName("net/http", "Redirect") }
184-
185-
override DataFlow::Node getUrl() { result = this.getArgument(2) }
186-
187-
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getArgument(0) }
188-
}
189-
190-
/** A call to a function in the `net/http` package that performs an HTTP request to a URL. */
191-
private class RequestCall extends HTTP::ClientRequest::Range, DataFlow::CallNode {
192-
RequestCall() {
193-
exists(string functionName |
194-
(
195-
this.getTarget().hasQualifiedName("net/http", functionName)
196-
or
197-
this.getTarget().(Method).hasQualifiedName("net/http", "Client", functionName)
198-
) and
199-
(functionName = "Get" or functionName = "Post" or functionName = "PostForm")
200-
)
201-
}
202-
203-
/** Gets the URL of the request. */
204-
override DataFlow::Node getUrl() { result = this.getArgument(0) }
205-
}
206-
207-
/** A call to the Client.Do function in the `net/http` package. */
208-
private class ClientDo extends HTTP::ClientRequest::Range, DataFlow::MethodCallNode {
209-
ClientDo() { this.getTarget().hasQualifiedName("net/http", "Client", "Do") }
210-
211-
override DataFlow::Node getUrl() {
212-
// A URL passed to `NewRequest`, whose result is passed to this `Do` call
213-
exists(DataFlow::CallNode call | call.getTarget().hasQualifiedName("net/http", "NewRequest") |
214-
this.getArgument(0) = call.getResult(0).getASuccessor*() and
215-
result = call.getArgument(1)
216-
)
217-
or
218-
// A URL passed to `NewRequestWithContext`, whose result is passed to this `Do` call
219-
exists(DataFlow::CallNode call |
220-
call.getTarget().hasQualifiedName("net/http", "NewRequestWithContext")
221-
|
222-
this.getArgument(0) = call.getResult(0).getASuccessor*() and
223-
result = call.getArgument(2)
224-
)
225-
or
226-
// A URL assigned to a request that is passed to this `Do` call
227-
exists(Write w, Field f |
228-
f.hasQualifiedName("net/http", "Request", "URL") and
229-
w.writesField(this.getArgument(0).getAPredecessor*(), f, result)
230-
)
231-
}
232-
}
233-
}
234-
2357
/**
2368
* Provides models of the go-restful library (https://github.com/emicklei/go-restful).
2379
*/

0 commit comments

Comments
 (0)