From: Aurelien DARRAGON Date: Thu, 6 Aug 2026 07:39:06 +0000 (+0200) Subject: BUG/MEDIUM: lua: resume Channel:send() from the unsent part of the string X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e85323dcebc5f270b0d2f69706230f0fbc4ac650;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: lua: resume Channel:send() from the unsent part of the string hlua_channel_send_yield() keeps in the number of bytes already pushed into the channel across yields, and correctly limits the amount it tries to push next to the remaining "sz - l" bytes. But it always passed the beginning of the string to _hlua_channel_insert(), so after a partial write the same prefix was sent again instead of the remainder. For a Lua script calling Channel:send() with more data than the channel can currently hold, the peer therefore receives the beginning of the buffer twice and never sees its tail. Any protocol framing carried over that stream is silently desynchronized, and the script has no way to notice since the returned count is correct. Let's advance the source pointer by the number of bytes already sent, as the applet send paths do. This was introduced in 2.5 by commit a1ac5fb28 ("MEDIUM: filters/lua: Be prepared to filter TCP payloads"). It must be backported to all stable versions. Reported-by: Claude (ANT-2026-GQE208VX) --- diff --git a/src/hlua.c b/src/hlua.c index 1f62dc53e..1958da548 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4591,7 +4591,8 @@ __LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext len = sz - l; } - ret = _hlua_channel_insert(chn, L, ist2(str, len), offset); + /* bytes were already sent by a previous pass, resume from there */ + ret = _hlua_channel_insert(chn, L, ist2(str + l, len), offset); if (ret == -1) { lua_pop(L, 1); lua_pushinteger(L, -1);