Skip to content

Commit e590b33

Browse files
author
Michael Hoisie
committed
Fixed bug in scgi parsing bodies with nil string
1 parent 3ee60f0 commit e590b33

File tree

2 files changed

+74
-29
lines changed

2 files changed

+74
-29
lines changed

scgi.go

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,51 @@ func (conn *scgiConn) Write(data []byte) (n int, err os.Error) {
5959

6060
func (conn *scgiConn) Close() { conn.fd.Close() }
6161

62-
func readScgiRequest(buf *bytes.Buffer) *Request {
62+
func readScgiRequest(buf *bytes.Buffer) (*Request, os.Error) {
6363
headers := make(map[string]string)
6464

65-
content := buf.Bytes()
66-
colon := bytes.IndexByte(content, ':')
67-
content = content[colon+1:]
68-
fields := bytes.Split(content, []byte{0}, 0)
65+
data := buf.Bytes()
66+
var clen int
67+
68+
colon := bytes.IndexByte(data, ':')
69+
data = data[colon+1:]
70+
var err os.Error
71+
//find the CONTENT_LENGTH
72+
73+
clfields := bytes.Split(data, []byte{0}, 3)
74+
if len(clfields) != 3 {
75+
return nil,os.NewError ("Invalid SCGI Request -- no fields")
76+
}
77+
78+
clfields = clfields[0:2]
79+
if string(clfields[0]) != "CONTENT_LENGTH"{
80+
return nil,os.NewError ("Invalid SCGI Request -- expecing CONTENT_LENGTH")
81+
}
82+
83+
if clen,err = strconv.Atoi ( string(clfields[1]) ); err != nil {
84+
return nil,os.NewError ("Invalid SCGI Request -- invalid CONTENT_LENGTH field")
85+
}
86+
87+
88+
content := data[ len(data) - clen : ]
89+
90+
println("clen", clen, len(content))
91+
92+
fields := bytes.Split ( data [ 0: len(data) - clen], []byte{0}, 0 )
93+
6994
for i := 0; i < len(fields)-1; i += 2 {
7095
key := string(fields[i])
7196
value := string(fields[i+1])
7297
headers[key] = value
7398
}
74-
var body bytes.Buffer
75-
body.Write(fields[len(fields)-1][1:])
7699

77-
req := newRequestCgi(headers, &body)
100+
body := bytes.NewBuffer(content)
101+
//var body bytes.Buffer
102+
//body.Write(content)
103+
104+
req := newRequestCgi(headers, body)
78105

79-
return req
106+
return req, nil
80107
}
81108

82109
func handleScgiRequest(fd io.ReadWriteCloser) {
@@ -92,17 +119,23 @@ func handleScgiRequest(fd io.ReadWriteCloser) {
92119
read := n
93120
length, _ := strconv.Atoi(string(tmp[0:colonPos]))
94121
buf.Write(tmp[0:n])
95-
122+
println("read", n)
96123
for read < length {
97124
n, err := fd.Read(&tmp)
98125
if err != nil || n == 0 {
99126
break
100127
}
128+
101129
buf.Write(tmp[0:n])
102130
read += n
103131
}
104132

105-
req := readScgiRequest(&buf)
133+
req,err := readScgiRequest(&buf)
134+
135+
if err != nil {
136+
log.Stderrf("SCGI read error", err.String())
137+
return;
138+
}
106139

107140
sc := scgiConn{fd, make(map[string][]string), false}
108141
routeHandler(req, &sc)

web_test.go

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,12 @@ func init() {
138138
var tests = []Test{
139139
Test{"GET", "/", "", 200, "index"},
140140
Test{"GET", "/echo/hello", "", 200, "hello"},
141+
Test{"GET", "/echo/hello", "", 200, "hello"},
141142
Test{"GET", "/multiecho/a/b/c/d", "", 200, "abcd"},
142143
Test{"POST", "/post/echo/hello", "", 200, "hello"},
144+
Test{"POST", "/post/echo/hello", "", 200, "hello"},
143145
Test{"POST", "/post/echoparam/a", "a=hello", 200, "hello"},
146+
Test{"POST", "/post/echoparam/a", "a=hello\x00", 200, "hello\x00"},
144147
//long url
145148
Test{"GET", "/echo/" + strings.Repeat("0123456789", 100), "", 200, strings.Repeat("0123456789", 100)},
146149

@@ -195,8 +198,8 @@ func TestRouting(t *testing.T) {
195198
}
196199
}
197200

198-
func buildScgiFields(fields map[string]string) []byte {
199-
var buf bytes.Buffer
201+
func buildScgiFields(fields map[string]string, buf *bytes.Buffer) []byte {
202+
200203
for k, v := range (fields) {
201204
buf.WriteString(k)
202205
buf.Write([]byte{0})
@@ -208,34 +211,40 @@ func buildScgiFields(fields map[string]string) []byte {
208211
}
209212

210213
func buildTestScgiRequest(method string, path string, body string, headers map[string]string) *bytes.Buffer {
214+
215+
var hbuf bytes.Buffer
211216
scgiHeaders := make(map[string]string)
212217

218+
hbuf.WriteString("CONTENT_LENGTH")
219+
hbuf.Write([]byte{0})
220+
hbuf.WriteString(fmt.Sprintf("%d", len(body)))
221+
hbuf.Write([]byte{0})
222+
213223
scgiHeaders["REQUEST_METHOD"] = method
214224
scgiHeaders["HTTP_HOST"] = "127.0.0.1"
215225
scgiHeaders["REQUEST_URI"] = path
216226
scgiHeaders["SERVER_PORT"] = "80"
217227
scgiHeaders["SERVER_PROTOCOL"] = "HTTP/1.1"
218228
scgiHeaders["USER_AGENT"] = "web.go test framework"
219229

230+
buildScgiFields(scgiHeaders, &hbuf)
231+
220232
if method == "POST" {
221233
headers["Content-Length"] = fmt.Sprintf("%d", len(body))
222234
headers["Content-Type"] = "text/plain"
223235
}
224236

225-
f1 := buildScgiFields(scgiHeaders)
226-
fields := f1
227-
228237
if len(headers) > 0 {
229-
f2 := buildScgiFields(headers)
230-
fields = bytes.Join([][]byte{f1, f2}, []byte{})
238+
buildScgiFields(headers, &hbuf)
231239
}
232-
233-
var buf bytes.Buffer
234-
235-
//comma at the end
236-
clen := len(fields) + len(body) + 1
237-
fmt.Fprintf(&buf, "%d:", clen)
238-
buf.Write(fields)
240+
241+
fielddata := hbuf.Bytes()
242+
var buf bytes.Buffer;
243+
244+
//extra 1 is for the comma at the end
245+
dlen := len(fielddata) + len(body) + 1
246+
fmt.Fprintf(&buf, "%d:", dlen)
247+
buf.Write(fielddata)
239248
buf.WriteString(",")
240249
buf.WriteString(body)
241250

@@ -289,17 +298,20 @@ func buildTestFcgiRequest(method string, path string, bodychunks []string, heade
289298
var req bytes.Buffer
290299
fcgiHeaders := make(map[string]string)
291300

301+
bodylength := 0
302+
for _, s := range (bodychunks) {
303+
bodylength += len(s)
304+
}
305+
306+
fcgiHeaders["CONTENT_LENGTH"] = fmt.Sprintf("%d", bodylength)
292307
fcgiHeaders["REQUEST_METHOD"] = method
293308
fcgiHeaders["HTTP_HOST"] = "127.0.0.1"
294309
fcgiHeaders["REQUEST_URI"] = path
295310
fcgiHeaders["SERVER_PORT"] = "80"
296311
fcgiHeaders["SERVER_PROTOCOL"] = "HTTP/1.1"
297312
fcgiHeaders["USER_AGENT"] = "web.go test framework"
298313

299-
bodylength := 0
300-
for _, s := range (bodychunks) {
301-
bodylength += len(s)
302-
}
314+
303315

304316
if method == "POST" {
305317
fcgiHeaders["Content-Length"] = fmt.Sprintf("%d", bodylength)

0 commit comments

Comments
 (0)