BUG/MEDIUM: mux-fcgi: Properly handle return value of headers/trailers parsing
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 28 Mar 2022 13:37:01 +0000 (15:37 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 28 Mar 2022 20:43:04 +0000 (22:43 +0200)
h1_parse_msg_hdrs() and h1_parse_msg_tlrs() may return negative values if
the parsing fails or if more space is needed in the destination buffer. When
h1-htx was changed, The H1 mux was updated accordingly but not the FCGI
mux. Thus if a negative value is returned, it is ignored and it is casted to
a size_t, leading to an integer overflow on the <ofs> value, used to know
the position in the RX buffer.

This patch must be backported as far as 2.2.

(cherry picked from commit d9fc12818e4084f76cfa1f31d20a5c17d83ecb3e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit bfe68e84b178fc5746e0d89a6519dedd1616754b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit d04f530228d4ae5141bb7a840edab35fab344b2f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/mux_fcgi.c

index caca72d..c868d0e 100644 (file)
@@ -3283,13 +3283,14 @@ static size_t fcgi_strm_parse_headers(struct fcgi_strm *fstrm, struct h1m *h1m,
 
        TRACE_ENTER(FCGI_EV_RSP_DATA|FCGI_EV_RSP_HDRS, fstrm->fconn->conn, fstrm, 0, (size_t[]){max});
        ret = h1_parse_msg_hdrs(h1m, NULL, htx, buf, *ofs, max);
-       if (!ret) {
+       if (ret <= 0) {
                TRACE_DEVEL("leaving on missing data or error", FCGI_EV_RSP_DATA|FCGI_EV_RSP_HDRS, fstrm->fconn->conn, fstrm);
                if (htx->flags & HTX_FL_PARSING_ERROR) {
                        TRACE_USER("rejected H1 response", FCGI_EV_RSP_DATA|FCGI_EV_RSP_HDRS|FCGI_EV_FSTRM_ERR, fstrm->fconn->conn, fstrm);
                        fcgi_strm_error(fstrm);
                        fcgi_strm_capture_bad_message(fstrm->fconn, fstrm, h1m, buf);
                }
+               ret = 0;
                goto end;
        }
 
@@ -3329,13 +3330,14 @@ static size_t fcgi_strm_parse_trailers(struct fcgi_strm *fstrm, struct h1m *h1m,
 
        TRACE_ENTER(FCGI_EV_RSP_DATA|FCGI_EV_RSP_TLRS, fstrm->fconn->conn, fstrm, 0, (size_t[]){max});
        ret = h1_parse_msg_tlrs(h1m, htx, buf, *ofs, max);
-       if (!ret) {
+       if (ret <= 0) {
                TRACE_DEVEL("leaving on missing data or error", FCGI_EV_RSP_DATA|FCGI_EV_RSP_TLRS, fstrm->fconn->conn, fstrm);
                if (htx->flags & HTX_FL_PARSING_ERROR) {
                        TRACE_USER("rejected H1 response", FCGI_EV_RSP_DATA|FCGI_EV_RSP_TLRS|FCGI_EV_FSTRM_ERR, fstrm->fconn->conn, fstrm);
                        fcgi_strm_error(fstrm);
                        fcgi_strm_capture_bad_message(fstrm->fconn, fstrm, h1m, buf);
                }
+               ret = 0;
                goto end;
        }
        *ofs += ret;