Skip to content

Commit 49234ee

Browse files
committed
net/http: panic on bogus use of CloseNotifier or Hijacker
Fixes #14001 Change-Id: I6f9bc3028345081758d8f537c3aaddb2e254e69e Reviewed-on: https://go-review.googlesource.com/18708 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 5c94f1a commit 49234ee

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

src/net/http/server.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ type response struct {
347347
// written.
348348
trailers []string
349349

350-
handlerDone bool // set true when the handler exits
350+
handlerDone atomicBool // set true when the handler exits
351351

352352
// Buffers for Date and Content-Length
353353
dateBuf [len(TimeFormat)]byte
@@ -358,6 +358,11 @@ type response struct {
358358
closeNotifyCh <-chan bool
359359
}
360360

361+
type atomicBool int32
362+
363+
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
364+
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
365+
361366
// declareTrailer is called for each Trailer header when the
362367
// response header is written. It notes that a header will need to be
363368
// written in the trailers at the end of the response.
@@ -911,7 +916,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
911916
// send a Content-Length header.
912917
// Further, we don't send an automatic Content-Length if they
913918
// set a Transfer-Encoding, because they're generally incompatible.
914-
if w.handlerDone && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
919+
if w.handlerDone.isSet() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
915920
w.contentLength = int64(len(p))
916921
setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
917922
}
@@ -1234,7 +1239,7 @@ func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err er
12341239
}
12351240

12361241
func (w *response) finishRequest() {
1237-
w.handlerDone = true
1242+
w.handlerDone.setTrue()
12381243

12391244
if !w.wroteHeader {
12401245
w.WriteHeader(StatusOK)
@@ -1498,6 +1503,9 @@ func (w *response) sendExpectationFailed() {
14981503
// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
14991504
// and a Hijacker.
15001505
func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
1506+
if w.handlerDone.isSet() {
1507+
panic("net/http: Hijack called after ServeHTTP finished")
1508+
}
15011509
if w.wroteHeader {
15021510
w.cw.flush()
15031511
}
@@ -1521,6 +1529,9 @@ func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
15211529
}
15221530

15231531
func (w *response) CloseNotify() <-chan bool {
1532+
if w.handlerDone.isSet() {
1533+
panic("net/http: CloseNotify called after ServeHTTP finished")
1534+
}
15241535
c := w.conn
15251536
c.mu.Lock()
15261537
defer c.mu.Unlock()

0 commit comments

Comments
 (0)