if cl == "" {
return -1
}
- n, err := strconv.ParseInt(cl, 10, 64)
+ n, err := strconv.ParseUint(cl, 10, 63)
if err != nil {
return -1
}
- return n
+ return int64(n)
}
})
}
}
+
+// issue 39017 - disallow Content-Length values such as "+3"
+func TestParseContentLength(t *testing.T) {
+ tests := []struct {
+ cl string
+ want int64
+ }{
+ {
+ cl: "3",
+ want: 3,
+ },
+ {
+ cl: "+3",
+ want: -1,
+ },
+ {
+ cl: "-3",
+ want: -1,
+ },
+ {
+ // max int64, for safe conversion before returning
+ cl: "9223372036854775807",
+ want: 9223372036854775807,
+ },
+ {
+ cl: "9223372036854775808",
+ want: -1,
+ },
+ }
+
+ for _, tt := range tests {
+ if got := parseContentLength(tt.cl); got != tt.want {
+ t.Errorf("%q:\n\tgot=%d\n\twant=%d", tt.cl, got, tt.want)
+ }
+ }
+}
if cl == "" {
return -1, nil
}
- n, err := strconv.ParseInt(cl, 10, 64)
- if err != nil || n < 0 {
+ n, err := strconv.ParseUint(cl, 10, 63)
+ if err != nil {
return 0, badStringError("bad Content-Length", cl)
}
- return n, nil
+ return int64(n), nil
}
}
}
}
+
+// issue 39017 - disallow Content-Length values such as "+3"
+func TestParseContentLength(t *testing.T) {
+ tests := []struct {
+ cl string
+ wantErr error
+ }{
+ {
+ cl: "3",
+ wantErr: nil,
+ },
+ {
+ cl: "+3",
+ wantErr: badStringError("bad Content-Length", "+3"),
+ },
+ {
+ cl: "-3",
+ wantErr: badStringError("bad Content-Length", "-3"),
+ },
+ {
+ // max int64, for safe conversion before returning
+ cl: "9223372036854775807",
+ wantErr: nil,
+ },
+ {
+ cl: "9223372036854775808",
+ wantErr: badStringError("bad Content-Length", "9223372036854775808"),
+ },
+ }
+
+ for _, tt := range tests {
+ if _, gotErr := parseContentLength(tt.cl); !reflect.DeepEqual(gotErr, tt.wantErr) {
+ t.Errorf("%q:\n\tgot=%v\n\twant=%v", tt.cl, gotErr, tt.wantErr)
+ }
+ }
+}
t.Error(err)
}
}
+
+// Issue 39017. Ensure that HTTP/1 transports reject Content-Length headers
+// that contain a sign (eg. "+3"), per RFC 2616, Section 14.13.
+func TestTransportRejectsSignInContentLength(t *testing.T) {
+ cst := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Content-Length", "+3")
+ w.Write([]byte("abc"))
+ }))
+ defer cst.Close()
+
+ c := cst.Client()
+ res, err := c.Get(cst.URL)
+ if err == nil || res != nil {
+ t.Fatal("Expected a non-nil error and a nil http.Response")
+ }
+ if got, want := err.Error(), `bad Content-Length "+3"`; !strings.Contains(got, want) {
+ t.Fatalf("Error mismatch\nGot: %q\nWanted substring: %q", got, want)
+ }
+}