diff options
Diffstat (limited to 'header.go')
-rw-r--r-- | header.go | 36 |
1 files changed, 26 insertions, 10 deletions
@@ -2870,24 +2870,40 @@ func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) { h.method = append(h.method[:0], b[:n]...) b = b[n+1:] - protoStr := strHTTP11 // parse requestURI n = bytes.LastIndexByte(b, ' ') - switch { - case n < 0: - h.noHTTP11 = true - n = len(b) - protoStr = strHTTP10 - case n == 0: + if n < 0 { + return 0, fmt.Errorf("cannot find whitespace in the first line of request %q", buf) + } else if n == 0 { if h.secureErrorLogMessage { return 0, fmt.Errorf("requestURI cannot be empty") } return 0, fmt.Errorf("requestURI cannot be empty in %q", buf) - case !bytes.Equal(b[n+1:], strHTTP11): - h.noHTTP11 = true - protoStr = b[n+1:] } + protoStr := b[n+1:] + + // Follow RFCs 7230 and 9112 and require that HTTP versions match the following pattern: HTTP/[0-9]\.[0-9] + if len(protoStr) != len(strHTTP11) { + if h.secureErrorLogMessage { + return 0, fmt.Errorf("unsupported HTTP version %q", protoStr) + } + return 0, fmt.Errorf("unsupported HTTP version %q in %q", protoStr, buf) + } + if !bytes.HasPrefix(protoStr, strHTTP11[:5]) { + if h.secureErrorLogMessage { + return 0, fmt.Errorf("unsupported HTTP version %q", protoStr) + } + return 0, fmt.Errorf("unsupported HTTP version %q in %q", protoStr, buf) + } + if protoStr[5] < '0' || protoStr[5] > '9' || protoStr[7] < '0' || protoStr[7] > '9' { + if h.secureErrorLogMessage { + return 0, fmt.Errorf("unsupported HTTP version %q", protoStr) + } + return 0, fmt.Errorf("unsupported HTTP version %q in %q", protoStr, buf) + } + + h.noHTTP11 = !bytes.Equal(protoStr, strHTTP11) h.proto = append(h.proto[:0], protoStr...) h.requestURI = append(h.requestURI[:0], b[:n]...) |