This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH COMMITTED] inet_pton: Reject IPv6 addresses with many leading zeros [BZ #16637]
- From: fweimer at redhat dot com (Florian Weimer)
- To: libc-alpha at sourceware dot org
- Date: Fri, 23 Jun 2017 23:06:09 +0200
- Subject: [PATCH COMMITTED] inet_pton: Reject IPv6 addresses with many leading zeros [BZ #16637]
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 9568F12287B
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 9568F12287B
2001:db8:00001::f is not a valid IPv6 address according to RFC 2373.
2017-06-23 Florian Weimer <fweimer@redhat.com>
[BZ #16637]
inet_pton: Reject invalid IPv6 addresses with many leading zeros.
* resolv/inet_pton.c (inet_pton6): Count number of hexadecimal
digits between colons.
* resolv/tst-inet_pton.c (test_cases): Adjust test expectations.
diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c
index b95da47..16ee33e 100644
--- a/resolv/inet_pton.c
+++ b/resolv/inet_pton.c
@@ -144,7 +144,8 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
{
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *curtok;
- int ch, saw_xdigit;
+ int ch;
+ size_t xdigits_seen; /* Number of hex digits since colon. */
unsigned int val;
tp = memset (tmp, '\0', NS_IN6ADDRSZ);
@@ -162,7 +163,7 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
}
curtok = src;
- saw_xdigit = 0;
+ xdigits_seen = 0;
val = 0;
while (src < src_endp)
{
@@ -170,17 +171,19 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
int digit = hex_digit_value (ch);
if (digit >= 0)
{
+ if (xdigits_seen == 4)
+ return 0;
val <<= 4;
val |= digit;
if (val > 0xffff)
return 0;
- saw_xdigit = 1;
+ ++xdigits_seen;
continue;
}
if (ch == ':')
{
curtok = src;
- if (!saw_xdigit)
+ if (xdigits_seen == 0)
{
if (colonp)
return 0;
@@ -193,7 +196,7 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
return 0;
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
- saw_xdigit = 0;
+ xdigits_seen = 0;
val = 0;
continue;
}
@@ -201,12 +204,12 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
&& inet_pton4 (curtok, src_endp, tp) > 0)
{
tp += NS_INADDRSZ;
- saw_xdigit = 0;
+ xdigits_seen = 0;
break; /* '\0' was seen by inet_pton4. */
}
return 0;
}
- if (saw_xdigit)
+ if (xdigits_seen > 0)
{
if (tp + NS_INT16SZ > endp)
return 0;
diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c
index 7fffb24..4bb9f81 100644
--- a/resolv/tst-inet_pton.c
+++ b/resolv/tst-inet_pton.c
@@ -226,13 +226,7 @@ const struct test_case test_cases[] =
},
{.input = "2", },
{.input = "2.", },
- {.input = "2001:db8:00001::f",
- .ipv6_ok = true,
- .ipv6_expected = {
- 0x20, 0x1, 0xd, 0xb8, 0x0, 0x1, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf
- },
- },
+ {.input = "2001:db8:00001::f", },
{.input = "2001:db8:10000::f", },
{.input = "2001:db8:1234:5678:abcd:ef01:2345:67",
.ipv6_ok = true,
@@ -454,13 +448,7 @@ const struct test_case test_cases[] =
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
},
},
- {.input = "::00001",
- .ipv6_ok = true,
- .ipv6_expected = {
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
- },
- },
+ {.input = "::00001", },
{.input = "::1",
.ipv6_ok = true,
.ipv6_expected = {