From 5cd00873f46f49f78587d4cc770e5ce7e979cc9c Mon Sep 17 00:00:00 2001 From: Tim Duesterhus Date: Fri, 26 Jun 2020 15:44:48 +0200 Subject: [PATCH] BUG/MEDIUM: fetch: Fix hdr_ip misparsing IPv4 addresses due to missing NUL The IPv4 code did not take into account that the header value might not contain the trailing NUL byte, possibly reading stray data after the header value, failing the parse and testing the IPv6 branch. That one adds the missing NUL, but fails to parse IPv4 addresses. Fix this issue by always adding the trailing NUL. The bug was reported on GitHub as issue #715. It's not entirely clear when this bug started appearing, possibly earlier versions of smp_fetch_hdr guaranteed the NUL termination. However the addition of the NUL in the IPv6 case was added together with IPv6 support, hinting that at that point in time the NUL was not guaranteed. The commit that added IPv6 support was 69fa99292e689e355080d83ab19db4698b7c502b which first appeared in HAProxy 1.5. This patch should be backported to 1.5+, taking into account the various buffer / chunk changes and the movement across different files. --- src/http_fetch.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/http_fetch.c b/src/http_fetch.c index aece90436..0d53afdf1 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -990,21 +990,19 @@ static int smp_fetch_hdr_val(const struct arg *args, struct sample *smp, const c static int smp_fetch_hdr_ip(const struct arg *args, struct sample *smp, const char *kw, void *private) { int ret; + struct buffer *temp = get_trash_chunk(); while ((ret = smp_fetch_hdr(args, smp, kw, private)) > 0) { - if (url2ipv4((char *) smp->data.u.str.area, &smp->data.u.ipv4)) { - smp->data.type = SMP_T_IPV4; - break; - } else { - struct buffer *temp = get_trash_chunk(); - if (smp->data.u.str.data < temp->size - 1) { - memcpy(temp->area, smp->data.u.str.area, - smp->data.u.str.data); - temp->area[smp->data.u.str.data] = '\0'; - if (inet_pton(AF_INET6, temp->area, &smp->data.u.ipv6)) { - smp->data.type = SMP_T_IPV6; - break; - } + if (smp->data.u.str.data < temp->size - 1) { + memcpy(temp->area, smp->data.u.str.area, + smp->data.u.str.data); + temp->area[smp->data.u.str.data] = '\0'; + if (url2ipv4((char *) temp->area, &smp->data.u.ipv4)) { + smp->data.type = SMP_T_IPV4; + break; + } else if (inet_pton(AF_INET6, temp->area, &smp->data.u.ipv6)) { + smp->data.type = SMP_T_IPV6; + break; } }