From: Christopher Faulet Date: Tue, 20 Oct 2026 12:46:51 +0000 (+0000) Subject: BUG/MEDIUM: hlua/filters: make HTTPMessage.eom/may_recv relative to the filter's... X-Git-Tag: v3.5-dev10~62 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=a6b7aa18dff0733ed5d012eb552b0a8f7a9b7481;p=haproxy.git BUG/MEDIUM: hlua/filters: make HTTPMessage.eom/may_recv relative to the filter's data HTTPMessage.eom() and HTTPMessage.may_recv() rely on the whole HTX message to know if more data are expected or not, by testing if the end of message was reached. However when several Lua filters are chained on a channel and an earlier one holds back some data (for instance to rewrite the body), the next ones may perform a test on data it should not see. This could lead to unexpected behavior, mainly by disclosing too early the end of the message to next layer. Now an help function is used to know if all data are visible or not. HTTPMessage.eom() is always false is all data are not visible by the current filter and HTTPMessage.may_recv() always true in that case. This should be backported to all supported versions but it will have to be adapted because the HTX API was changed in 3.5. --- diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index 20364e79a..e2350ff1f 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -4485,10 +4485,13 @@ HTTPMessage class .. js:function:: HTTPMessage.eom(http_msg) This function returns true if the end of message is reached for the HTTP - message **http_msg**. + message **http_msg**. When called by a filter, the result is relative to the + data visible by this filter: if an earlier filter holds back some data, the + function always returns false, even if the end of the message was received, + because the held data may still carry it. :param class_httpmessage http_msg: The manipulated HTTP message. - :returns: an integer containing the amount of available bytes. + :returns: a boolean .. js:function:: HTTPMessage.del_header(http_msg, name) @@ -4590,7 +4593,10 @@ HTTPMessage class .. js:function:: HTTPMessage.may_recv(http_msg) This function returns true if the HTTP message **http_msg** may still receive - data. + data. When called by a filter, the result is relative to the data visible by + this filter: if an earlier filter holds back some data, the function always + returns true, because the held data may still be exposed to the current + filter, even if nothing will be received anymore. :param class_httpmessage http_msg: The manipulated HTTP message. :returns: a boolean diff --git a/src/hlua.c b/src/hlua.c index f2f12b23c..6e2ab7ccb 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -6915,6 +6915,17 @@ static struct filter *hlua_http_msg_filter(lua_State *L, int ud, struct http_msg return filter; } +/* Helper function to know if all data in an HTX message are visible. + * Returns 1 if no filter are attached to the HTTP message or if all HTX data are + * visible by the filter Otherwise 0 is returned. */ +static int hlua_http_msg_fully_visible(lua_State *L, struct http_msg *msg, struct htx *htx) +{ + size_t offset, len; + + hlua_http_msg_filter(L, 1, msg, &offset, &len); + return (offset + len == htx->data); +} + /* Returns true if the channel attached to the HTTP message is the response * channel. */ @@ -7263,11 +7274,16 @@ __LJMP static int hlua_http_msg_may_recv(lua_State *L) { struct http_msg *msg; struct htx *htx; + int may_recv; MAY_LJMP(check_args(L, 1, "may_recv")); msg = MAY_LJMP(hlua_checkhttpmsg(L, 1)); htx = htxbuf(&msg->chn->buf); - lua_pushboolean(L, (htx_expect_more(htx) && !channel_input_closed(msg->chn) && channel_may_recv(msg->chn))); + may_recv = !hlua_http_msg_fully_visible(L, msg, htx) || (htx_expect_more(htx) && + !channel_input_closed(msg->chn) && + channel_may_recv(msg->chn)); + + lua_pushboolean(L, may_recv); return 1; } @@ -7276,11 +7292,13 @@ __LJMP static int hlua_http_msg_is_eom(lua_State *L) { struct http_msg *msg; struct htx *htx; + int eom; - MAY_LJMP(check_args(L, 1, "may_recv")); + MAY_LJMP(check_args(L, 1, "eom")); msg = MAY_LJMP(hlua_checkhttpmsg(L, 1)); htx = htxbuf(&msg->chn->buf); - lua_pushboolean(L, !htx_expect_more(htx)); + eom = hlua_http_msg_fully_visible(L, msg, htx) && htx_msg_ended(htx); + lua_pushboolean(L, eom); return 1; }