aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Solomon <msolo@gmail.com>2011-11-01 10:31:29 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2011-11-01 10:31:29 -0700
commitf753e3facda2a9845caf7e8aed0e8a122d6b6e48 (patch)
treee17219c0e1a474ae52a4fc854e77eed96b311844
parentcf7281e7289ffe861e2bfcac14d2e1b40416d741 (diff)
downloadgo-f753e3facda2a9845caf7e8aed0e8a122d6b6e48.tar.gz
go-f753e3facda2a9845caf7e8aed0e8a122d6b6e48.zip
textproto: prevent long lines in HTTP headers from causing HTTP 400 responses.
This fixes the issue without an extra copy in the average case. R=golang-dev, ality, bradfitz CC=golang-dev https://golang.org/cl/5272049
-rw-r--r--src/pkg/net/textproto/reader.go18
-rw-r--r--src/pkg/net/textproto/reader_test.go17
2 files changed, 33 insertions, 2 deletions
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index ece9a99ffb..98b39276b8 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -50,8 +50,22 @@ func (r *Reader) ReadLineBytes() ([]byte, os.Error) {
func (r *Reader) readLineSlice() ([]byte, os.Error) {
r.closeDot()
- line, _, err := r.R.ReadLine()
- return line, err
+ var line []byte
+ for {
+ l, more, err := r.R.ReadLine()
+ if err != nil {
+ return nil, err
+ }
+ // Avoid the copy if the first call produced a full line.
+ if line == nil && !more {
+ return l, nil
+ }
+ line = append(line, l...)
+ if !more {
+ break
+ }
+ }
+ return line, nil
}
// ReadContinuedLine reads a possibly continued line from r,
diff --git a/src/pkg/net/textproto/reader_test.go b/src/pkg/net/textproto/reader_test.go
index 23ebc3f61e..a087e29d91 100644
--- a/src/pkg/net/textproto/reader_test.go
+++ b/src/pkg/net/textproto/reader_test.go
@@ -139,6 +139,23 @@ func TestReadMIMEHeader(t *testing.T) {
}
}
+func TestLargeReadMIMEHeader(t *testing.T) {
+ data := make([]byte, 16*1024)
+ for i := 0; i < len(data); i++ {
+ data[i] = 'x'
+ }
+ sdata := string(data)
+ r := reader("Cookie: " + sdata + "\r\n\n")
+ m, err := r.ReadMIMEHeader()
+ if err != nil {
+ t.Fatalf("ReadMIMEHeader: %v", err)
+ }
+ cookie := m.Get("Cookie")
+ if cookie != sdata {
+ t.Fatalf("ReadMIMEHeader: %v bytes, want %v bytes", len(cookie), len(sdata))
+ }
+}
+
type readResponseTest struct {
in string
inCode int