From: Willy Tarreau Date: Thu, 21 May 2026 13:00:12 +0000 (+0200) Subject: BUG/MEDIUM: net_helper: fix a remaining possibly infinite loop in converters X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=413f6f9a1f74590b064587f539c985c3c2bf0c9e;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: net_helper: fix a remaining possibly infinite loop in converters The various tcp_option_* converters rely on tcp_fullhdr_find_opt() to find the option. However, the same bug as fixed in commit dbf471f99a ("BUG/MAJOR: net_helper: ip.fp infinite loop on malformed tcp options") was also present there, by which an option of length 0 could be looped over indefinitely. In practice this does not happen since such options are not valid, but if passed encoded in an HTTP header for example, it could possibly be passed. While fixing it, let's check for length >1 in all 3 locations insteead of only non-zero, since there's no point processing a malformed option that wouldn't even be properly skipped. This fix doesn't need to be backported, unless the ip.fp series is. Thanks to @Vincent55 for reporting this issue. --- diff --git a/src/net_helper.c b/src/net_helper.c index 84e6b86d8..85990a289 100644 --- a/src/net_helper.c +++ b/src/net_helper.c @@ -447,8 +447,8 @@ static size_t tcp_fullhdr_find_opt(const struct sample *smp, uint8_t opt) /* kind1 = NOP and is a single byte, others have a length field */ if (smp->data.u.str.area[next] == 1) next++; - else if (next + 1 < len) - next += smp->data.u.str.area[next + 1]; + else if (next + 1 < len && smp->data.u.str.area[next + 1] > 1) + next += (uchar)smp->data.u.str.area[next + 1]; else break; if (smp->data.u.str.area[curr] == opt && next <= len) @@ -605,7 +605,7 @@ static int sample_conv_tcp_options_list(const struct arg *arg_p, struct sample * /* kind1 = NOP and is a single byte, others have a length field */ if (smp->data.u.str.area[ofs] == 1) ofs++; - else if (ofs + 1 < len && smp->data.u.str.area[ofs + 1]) + else if (ofs + 1 < len && smp->data.u.str.area[ofs + 1] > 1) ofs += (uchar)smp->data.u.str.area[ofs + 1]; else break; @@ -780,7 +780,7 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void * /* kind1 = NOP and is a single byte, others have a length field */ if (smp->data.u.str.area[ofs] == 1) next = ofs + 1; - else if ((ofs + 1 < tcplen) && smp->data.u.str.area[ofs + 1]) /* optlen 0 will cause an infinite loop */ + else if ((ofs + 1 < tcplen) && smp->data.u.str.area[ofs + 1] > 1) next = ofs + (uchar)smp->data.u.str.area[ofs + 1]; else break;