diff --git a/src/core/headers.ml b/src/core/headers.ml index eb140b66..d6abb17a 100644 --- a/src/core/headers.ml +++ b/src/core/headers.ml @@ -83,8 +83,13 @@ let parse_line_ (line : string) : _ result = Ok (k, v) with Failure msg -> Error msg -let parse_ ~(buf : Buf.t) (bs : IO.Input.t) : t = - let rec loop acc = +let parse_ ~(buf : Buf.t) ?(max_headers = 100) ?(max_header_size = 16384) + ?(max_total_size = 1048576) (bs : IO.Input.t) : t = + let rec loop acc count total_size = + if count >= max_headers then + bad_reqf 431 "too many headers (max: %d)" max_headers; + if total_size >= max_total_size then + bad_reqf 431 "headers too large (max: %d bytes)" max_total_size; match IO.Input.read_line_using_opt ~buf bs with | None -> raise End_of_file | Some "" -> assert false @@ -92,12 +97,15 @@ let parse_ ~(buf : Buf.t) (bs : IO.Input.t) : t = | Some line when line.[String.length line - 1] <> '\r' -> bad_reqf 400 "bad header line, not ended in CRLF" | Some line -> + let line_len = String.length line in + if line_len > max_header_size then + bad_reqf 431 "header too large (max: %d bytes)" max_header_size; let k, v = match parse_line_ line with | Ok r -> r | Error msg -> bad_reqf 400 "invalid header line: %s\nline is: %S" msg line in - loop ((k, v) :: acc) + loop ((k, v) :: acc) (count + 1) (total_size + line_len) in - loop [] + loop [] 0 0 diff --git a/src/core/headers.mli b/src/core/headers.mli index 8a1dfab5..ea12b209 100644 --- a/src/core/headers.mli +++ b/src/core/headers.mli @@ -34,7 +34,13 @@ val pp : Format.formatter -> t -> unit (**/*) -val parse_ : buf:Buf.t -> IO.Input.t -> t +val parse_ : + buf:Buf.t -> + ?max_headers:int -> + ?max_header_size:int -> + ?max_total_size:int -> + IO.Input.t -> + t val parse_line_ : string -> (string * string, string) result (**/*) diff --git a/src/core/response_code.ml b/src/core/response_code.ml index 54052268..b0ff8ac8 100644 --- a/src/core/response_code.ml +++ b/src/core/response_code.ml @@ -25,6 +25,7 @@ let descr = function | 411 -> "Length required" | 413 -> "Payload too large" | 417 -> "Expectation failed" + | 431 -> "Request Header Fields Too Large" | 500 -> "Internal server error" | 501 -> "Not implemented" | 503 -> "Service unavailable"