]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: fetch: Fix hdr_ip misparsing IPv4 addresses due to missing NUL
authorTim Duesterhus <tim@bastelstu.be>
Fri, 26 Jun 2020 13:44:48 +0000 (15:44 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 26 Jun 2020 15:42:41 +0000 (17:42 +0200)
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

index aece904360da84ad576afd1cb9a900c88ff15123..0d53afdf13cdeaa04bc77889fccc64c5c1dd6479 100644 (file)
@@ -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;
                        }
                }