From: ian woolf Date: Sat, 10 Apr 2021 07:41:13 +0000 (+0800) Subject: net/http/httptest: panic on non-3 digit (XXX) status code in Recorder.WriteHeader X-Git-Tag: go1.17beta1~641 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c3931ab1b7bceddc56479d7ddbd7517d244bfe17;p=gostls13.git net/http/httptest: panic on non-3 digit (XXX) status code in Recorder.WriteHeader This change conforms Recorder with net/http servers, to panic when a handler writes a non-3 digit XXX status code. Fixes #45353 Change-Id: Id5ed4af652e8c150ae86bf50402b800d935e2203 Reviewed-on: https://go-review.googlesource.com/c/go/+/308950 Reviewed-by: Emmanuel Odeke Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Trust: Michael Knyszek --- diff --git a/src/net/http/httptest/recorder.go b/src/net/http/httptest/recorder.go index 2428482612..1b712ef2b0 100644 --- a/src/net/http/httptest/recorder.go +++ b/src/net/http/httptest/recorder.go @@ -122,11 +122,30 @@ func (rw *ResponseRecorder) WriteString(str string) (int, error) { return len(str), nil } +func checkWriteHeaderCode(code int) { + // Issue 22880: require valid WriteHeader status codes. + // For now we only enforce that it's three digits. + // In the future we might block things over 599 (600 and above aren't defined + // at https://httpwg.org/specs/rfc7231.html#status.codes) + // and we might block under 200 (once we have more mature 1xx support). + // But for now any three digits. + // + // We used to send "HTTP/1.1 000 0" on the wire in responses but there's + // no equivalent bogus thing we can realistically send in HTTP/2, + // so we'll consistently panic instead and help people find their bugs + // early. (We can't return an error from WriteHeader even if we wanted to.) + if code < 100 || code > 999 { + panic(fmt.Sprintf("invalid WriteHeader code %v", code)) + } +} + // WriteHeader implements http.ResponseWriter. func (rw *ResponseRecorder) WriteHeader(code int) { if rw.wroteHeader { return } + + checkWriteHeaderCode(code) rw.Code = code rw.wroteHeader = true if rw.HeaderMap == nil { diff --git a/src/net/http/httptest/recorder_test.go b/src/net/http/httptest/recorder_test.go index a865e878b9..8cb32dd740 100644 --- a/src/net/http/httptest/recorder_test.go +++ b/src/net/http/httptest/recorder_test.go @@ -345,3 +345,28 @@ func TestParseContentLength(t *testing.T) { } } } + +// Ensure that httptest.Recorder panics when given a non-3 digit (XXX) +// status HTTP code. See https://golang.org/issues/45353 +func TestRecorderPanicsOnNonXXXStatusCode(t *testing.T) { + badCodes := []int{ + -100, 0, 99, 1000, 20000, + } + for _, badCode := range badCodes { + badCode := badCode + t.Run(fmt.Sprintf("Code=%d", badCode), func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("Expected a panic") + } + }() + + handler := func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(badCode) + } + r, _ := http.NewRequest("GET", "http://example.org/", nil) + rw := NewRecorder() + handler(rw, r) + }) + } +}