]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: Don't release H1 stream upgraded from TCP on error
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 15 Dec 2022 08:22:35 +0000 (09:22 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 15 Dec 2022 08:51:31 +0000 (09:51 +0100)
When an error occurred during the request parsing, the H1 multiplexer is
responsible to sent a response to the client and to release the H1 stream
and the H1 connection. In HTTP mode, it is not an issue because at this
stage the H1 connection is in embryonic state. Thus it can be released
immediately.

However, it is a problem if the connection was first upgraded from a TCP
connection. In this case, a stream-connector is attached. The H1 stream is
not orphan. Thus it must not be released at this stage. It must be detached
first. Otherwise a BUG_ON() is triggered in h1s_destroy().

So now, the H1S is destroyed on early errors but only if the H1C is in
embryonic state.

This patch may be related to #1966. It must be backported to 2.7.

reg-tests/connection/tcp_to_http_upgrade.vtc
src/mux_h1.c

index 093ba48e1377daa86bfb54bc81735c5ac127e949..48ebebaef7649b9ab7ae709d28bfe81cd25ca82c 100644 (file)
@@ -155,6 +155,13 @@ client c_err3 -connect ${h1_err3h1_sock} {
     expect_close
 } -run
 
+# TCP > HTTP upgrade with a parsing error
+client c_err4 -connect ${h1_fe2h1_sock} {
+    send "GET / BAD-VERSION\r\n\r\n"
+    rxresp
+    expect resp.status == 400
+} -run
+
 # To be sure no other request was received by the server
 client c_end -connect ${s1_sock} {
     txreq
index a8421b76ca00a5710505b64c0b95426145bb7a6e..c511cfede77ff6c01725f858e3a32d3e3cdab812 100644 (file)
@@ -2629,7 +2629,8 @@ static int h1_send_error(struct h1c *h1c)
                }
        }
 
-       if (h1c->h1s) {
+       if (h1c->state == H1_CS_EMBRYONIC) {
+               BUG_ON(h1c->h1s == NULL || h1s_sc(h1c->h1s) == NULL);
                TRACE_DEVEL("Abort embryonic H1S", H1_EV_H1C_ERR, h1c->conn, h1c->h1s);
                h1s_destroy(h1c->h1s);
        }