]> Cypherpunks repositories - gostls13.git/commitdiff
net/textproto: ignore initial lines with leading whitespaces in ReadMIMEHeader
authorWèi Cōngruì <crvv.mail@gmail.com>
Thu, 2 Nov 2017 06:23:32 +0000 (14:23 +0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 10 Nov 2017 04:51:55 +0000 (04:51 +0000)
A header line with leading whitespaces is not valid in HTTP as per
RFC7230. This change ignores these invalid lines in ReadMIMEHeader.

Updates #22464

Change-Id: Iff9f00380d28a9617a55ff7888a76fba82001402
Reviewed-on: https://go-review.googlesource.com/75350
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/http/readrequest_test.go
src/net/http/response_test.go
src/net/textproto/reader.go
src/net/textproto/reader_test.go

index 28a148b9acb63787312d516ecdd4e07a42288af2..21c0e098bf79ef0360b0cecebd800f7c207ea10f 100644 (file)
@@ -401,6 +401,26 @@ var reqTests = []reqTest{
                noTrailer,
                noError,
        },
+
+       // leading whitespace in the first header. golang.org/issue/22464
+       {
+               "GET / HTTP/1.1\r\n Foobar: ignored\r\nConnection: close\r\n\r\n",
+               &Request{
+                       Method: "GET",
+                       URL: &url.URL{
+                               Path: "/",
+                       },
+                       Header:     Header{"Connection": {"close"}},
+                       Proto:      "HTTP/1.1",
+                       ProtoMajor: 1,
+                       ProtoMinor: 1,
+                       RequestURI: "/",
+                       Close:      true,
+               },
+               noBodyStr,
+               noTrailer,
+               noError,
+       },
 }
 
 func TestReadRequest(t *testing.T) {
index f1a50bd59891ae62dcd890daeced95b6129fb112..484a89e46dbd14419772a74b3ec9f43be3059c85 100644 (file)
@@ -555,6 +555,28 @@ some body`,
                },
                "Your Authentication failed.\r\n",
        },
+
+       // leading whitespace in the first header. golang.org/issue/22464
+       {
+               "HTTP/1.1 200 OK\r\n" +
+                       " Content-type: text/html\r\n" +
+                       "\tIgnore: foobar\r\n" +
+                       "Foo: bar\r\n\r\n",
+               Response{
+                       Status:     "200 OK",
+                       StatusCode: 200,
+                       Proto:      "HTTP/1.1",
+                       ProtoMajor: 1,
+                       ProtoMinor: 1,
+                       Request:    dummyReq("GET"),
+                       Header: Header{
+                               "Foo": {"bar"},
+                       },
+                       Close:         true,
+                       ContentLength: -1,
+               },
+               "",
+       },
 }
 
 // tests successful calls to ReadResponse, and inspects the returned Response.
index e07d1d62e0931e653e71ee169a3540d036c04e3b..c5e0b7591e84c9ed0a72a94f1c92db2b4774a229 100644 (file)
@@ -476,6 +476,14 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
        }
 
        m := make(MIMEHeader, hint)
+
+       for r.skipSpace() > 0 {
+               line, err := r.readLineSlice()
+               if len(line) == 0 || err != nil {
+                       return m, err
+               }
+       }
+
        for {
                kv, err := r.readContinuedLineSlice()
                if len(kv) == 0 {
index 6cd98ed1b543e53aeac5467f8030842eed038fd4..b26765e3cd691ebf60ccb348795cadeb38203565 100644 (file)
@@ -211,6 +211,25 @@ func TestReadMIMEHeaderNonCompliant(t *testing.T) {
        }
 }
 
+func TestReadMIMEHeaderLeadingSpace(t *testing.T) {
+       tests := []struct {
+               input string
+               want  MIMEHeader
+       }{
+               {" Ignore: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
+               {"\tIgnore: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
+               {" Ignore1: ignore\r\n Ignore2: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
+               {" Ignore1: ignore\r\n\r\n", MIMEHeader{}},
+       }
+       for _, tt := range tests {
+               r := reader(tt.input)
+               m, err := r.ReadMIMEHeader()
+               if !reflect.DeepEqual(m, tt.want) || err != nil {
+                       t.Errorf("ReadMIMEHeader(%q) = %v, %v; want %v", tt.input, m, err, tt.want)
+               }
+       }
+}
+
 // Test that continued lines are properly trimmed. Issue 11204.
 func TestReadMIMEHeaderTrimContinued(t *testing.T) {
        // In this header, \n and \r\n terminated lines are mixed on purpose.