mirror of
https://github.com/c-cube/tiny_httpd.git
synced 2026-03-08 06:47:59 -04:00
fix: add header size limits to prevent memory exhaustion
Add optional limits to Headers.parse_: - max_headers: 100 (default) - max_header_size: 16KB per header (default) - max_total_size: 1MB total (default) Returns 431 status code when limits exceeded per RFC 6585.
This commit is contained in:
parent
8050fb1f05
commit
1f357e495a
3 changed files with 20 additions and 5 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
(**/*)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue