Commit 3caf4e05 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: check max size of HTTP chunks

Thanks to Régis Leroy for noticing.

Change-Id: I5ca2402efddab4e63d884a9d315fc1394e514cb7
Reviewed-on: https://go-review.googlesource.com/18871Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 801bebef
...@@ -220,8 +220,7 @@ type FlushAfterChunkWriter struct { ...@@ -220,8 +220,7 @@ type FlushAfterChunkWriter struct {
} }
func parseHexUint(v []byte) (n uint64, err error) { func parseHexUint(v []byte) (n uint64, err error) {
for _, b := range v { for i, b := range v {
n <<= 4
switch { switch {
case '0' <= b && b <= '9': case '0' <= b && b <= '9':
b = b - '0' b = b - '0'
...@@ -232,6 +231,10 @@ func parseHexUint(v []byte) (n uint64, err error) { ...@@ -232,6 +231,10 @@ func parseHexUint(v []byte) (n uint64, err error) {
default: default:
return 0, errors.New("invalid byte in chunk length") return 0, errors.New("invalid byte in chunk length")
} }
if i == 16 {
return 0, errors.New("http chunk length too large")
}
n <<= 4
n |= uint64(b) n |= uint64(b)
} }
return return
......
...@@ -139,19 +139,35 @@ func TestChunkReaderAllocs(t *testing.T) { ...@@ -139,19 +139,35 @@ func TestChunkReaderAllocs(t *testing.T) {
} }
func TestParseHexUint(t *testing.T) { func TestParseHexUint(t *testing.T) {
type testCase struct {
in string
want uint64
wantErr string
}
tests := []testCase{
{"x", 0, "invalid byte in chunk length"},
{"0000000000000000", 0, ""},
{"0000000000000001", 1, ""},
{"ffffffffffffffff", 1<<64 - 1, ""},
{"000000000000bogus", 0, "invalid byte in chunk length"},
{"00000000000000000", 0, "http chunk length too large"}, // could accept if we wanted
{"10000000000000000", 0, "http chunk length too large"},
{"00000000000000001", 0, "http chunk length too large"}, // could accept if we wanted
}
for i := uint64(0); i <= 1234; i++ { for i := uint64(0); i <= 1234; i++ {
line := []byte(fmt.Sprintf("%x", i)) tests = append(tests, testCase{in: fmt.Sprintf("%x", i), want: i})
got, err := parseHexUint(line) }
if err != nil { for _, tt := range tests {
t.Fatalf("on %d: %v", i, err) got, err := parseHexUint([]byte(tt.in))
if tt.wantErr != "" {
if !strings.Contains(fmt.Sprint(err), tt.wantErr) {
t.Errorf("parseHexUint(%q) = %v, %v; want error %q", tt.in, got, err, tt.wantErr)
} }
if got != i { } else {
t.Errorf("for input %q = %d; want %d", line, got, i) if err != nil || got != tt.want {
t.Errorf("parseHexUint(%q) = %v, %v; want %v", tt.in, got, err, tt.want)
} }
} }
_, err := parseHexUint([]byte("bogus"))
if err == nil {
t.Error("expected error on bogus input")
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment