BUG/MEDIUM: h1: limit status codes to 3 digits by default

By default, HTTP/1 status codes are not limited in the parser. However,
the value is stored in a 16-bit field, meaning that it may be truncated
if too large. Let's just restrict to 3-digits by default, and permit to
relax the check when accept-unsafe-violations is set, provided that the
value still fits in 16 bits.

This could be backported to latest LTS release.
This commit is contained in:
Willy Tarreau 2026-05-24 19:58:52 +02:00
parent 0e12369026
commit b37b5e8bcf
2 changed files with 13 additions and 0 deletions

View file

@ -10027,6 +10027,9 @@ no option accept-unsafe-violations-in-http-response
When this option is set, the following rules are observed:
* In H1 only, status codes longer than 3 digits but whose value fits in 16
bits are not rejected.
* In H1 only, invalid characters, including NULL character, in header name
will not be rejected; however the header will be dropped.

View file

@ -710,6 +710,16 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
case H1_MSG_RPCODE:
http_msg_rpcode:
if (likely(HTTP_IS_DIGIT(*ptr))) {
if (ptr - sl.st.c.ptr >= 3) {
/* more than 3 digits */
if (h1m->err_pos == -1) /* only capture the error pointer */
h1m->err_pos = ptr - start + skip;
else if (h1m->err_pos < -1 || sl.st.status >= ((uint16_t)~0 - 9) / 10) {
/* strict checks or risk of overflow */
state = H1_MSG_RPCODE;
goto http_msg_invalid;
}
}
sl.st.status = sl.st.status * 10 + *ptr - '0';
EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode, http_msg_ood, state, H1_MSG_RPCODE);
}