From: Christopher Faulet Date: Mon, 18 Nov 2024 21:19:00 +0000 (+0100) Subject: MINIR: mux-h1: Return 414 or 431 when appropriate X-Git-Tag: v3.1-dev14~100 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bc967758a21a2aa872109a1b24cb94887eb0629f;p=thirdparty%2Fhaproxy.git MINIR: mux-h1: Return 414 or 431 when appropriate When the request is too large to fit in a buffer a 414 or a 431 error message is returned depending on the error state of the request parser. A 414 is returned if the URI is too long, otherwise a 431 is returned. This patch should fix the issue #1309. --- diff --git a/include/haproxy/h1.h b/include/haproxy/h1.h index b4e66908e0..5dcbc4f80d 100644 --- a/include/haproxy/h1.h +++ b/include/haproxy/h1.h @@ -131,6 +131,7 @@ struct h1m { uint64_t curr_len; // content-length or last chunk length uint64_t body_len; // total known size of the body length uint32_t next; // next byte to parse, relative to buffer's head + unsigned int err_code; // the HTTP status code corresponding to the error, if it can be specified (0: unset) int err_pos; // position in the byte stream of the first error (H1 or H2) int err_state; // state where the first error was met (H1 or H2) }; @@ -358,6 +359,7 @@ static inline struct h1m *h1m_init_req(struct h1m *h1m) h1m->flags = H1_MF_NONE; h1m->curr_len = 0; h1m->body_len = 0; + h1m->err_code = 0; h1m->err_pos = -2; h1m->err_state = 0; return h1m; @@ -371,6 +373,7 @@ static inline struct h1m *h1m_init_res(struct h1m *h1m) h1m->flags = H1_MF_RESP; h1m->curr_len = 0; h1m->body_len = 0; + h1m->err_code = 0; h1m->err_pos = -2; h1m->err_state = 0; return h1m; diff --git a/src/h1_htx.c b/src/h1_htx.c index 37364b8c29..33a86faa7f 100644 --- a/src/h1_htx.c +++ b/src/h1_htx.c @@ -163,8 +163,10 @@ static int h1_postparse_req_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx * size allowed. */ if (h1_eval_htx_size(meth, uri, vsn, hdrs) > max) { - if (htx_is_empty(htx)) + if (htx_is_empty(htx)) { + h1m->err_code = 431; goto error; + } goto output_full; } @@ -364,8 +366,13 @@ int h1_parse_msg_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx *dsthtx, * contains headers and is full, which is detected by it being * full and the offset to be zero, it's an error because * headers are too large to be handled by the parser. */ - if (ret < 0 || (!ret && !ofs && !buf_room_for_htx_data(srcbuf))) + if (ret < 0) + goto error; + if (!ret && !ofs && !buf_room_for_htx_data(srcbuf)) { + if (!(h1m->flags & H1_MF_RESP)) + h1m->err_code = (h1m->err_state < H1_MSG_HDR_FIRST) ? 414: 431; goto error; + } goto end; } total = ret; diff --git a/src/mux_h1.c b/src/mux_h1.c index 6504477638..0382427634 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1926,6 +1926,8 @@ static size_t h1_handle_headers(struct h1s *h1s, struct h1m *h1m, struct htx *ht TRACE_DEVEL("leaving on missing data or error", H1_EV_RX_DATA|H1_EV_RX_HDRS, h1s->h1c->conn, h1s); if (ret == -1) { h1s->flags |= H1S_F_PARSING_ERROR; + if (h1m->err_code) + h1s->h1c->errcode = h1m->err_code; TRACE_ERROR("parsing error, reject H1 message", H1_EV_RX_DATA|H1_EV_RX_HDRS|H1_EV_H1S_ERR, h1s->h1c->conn, h1s); h1_capture_bad_message(h1s->h1c, h1s, h1m, buf); }