diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-06-23 22:51:00 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-06-23 22:51:06 +0200 |
commit | 9a0cc8c1bd7645bf3c988890ffb59639c07a5812 (patch) | |
tree | 8de136777f54b60d406e5fcd5f64889c2e5949ea | |
parent | fa872e1b6210e81e60d6029429f0a083b8eab26e (diff) | |
download | glibc-9a0cc8c1bd7645bf3c988890ffb59639c07a5812.tar glibc-9a0cc8c1bd7645bf3c988890ffb59639c07a5812.tar.gz glibc-9a0cc8c1bd7645bf3c988890ffb59639c07a5812.tar.bz2 glibc-9a0cc8c1bd7645bf3c988890ffb59639c07a5812.zip |
inet_pton: Reject IPv6 addresses with many leading zeros [BZ #16637]
2001:db8:00001::f is not a valid IPv6 address according to RFC 2373.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | resolv/inet_pton.c | 17 | ||||
-rw-r--r-- | resolv/tst-inet_pton.c | 16 |
3 files changed, 20 insertions, 21 deletions
@@ -1,3 +1,11 @@ +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. + 2017-05-23 Adhemerval Zanella <adhemerval.zanella@linaro.org> Juan Manuel Torres Palma <jmtorrespalma@gmail.com> diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c index b95da47c17..16ee33e0c0 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 7fffb24cdf..4bb9f81193 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 = { |