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.
This commit is contained in:
Willy Tarreau 2026-05-21 15:00:12 +02:00
parent 3475a5bb9f
commit 413f6f9a1f

View file

@ -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;