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.
(cherry picked from commit 5cd00873f46f49f78587d4cc770e5ce7e979cc9c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 1b752a347dc709520e5d1cd475b1ad783fe5897c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/http_fetch.c b/src/http_fetch.c
index 487333d..9e6113b 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -1563,21 +1563,19 @@
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;
}
}