diff mbox

[COMMITTED] inet_pton: Reject IPv6 addresses with many leading zeros [BZ #16637]

Message ID 20170623210609.71FE4439942F0@oldenburg.str.redhat.com
State New
Headers show

Commit Message

Florian Weimer June 23, 2017, 9:06 p.m. UTC
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.

Comments

Andreas Schwab June 24, 2017, 6:57 a.m. UTC | #1
On Jun 23 2017, fweimer@redhat.com (Florian Weimer) wrote:

>    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.  */

No need for size_t, it can only be 4 at most.

Andreas.
Florian Weimer June 24, 2017, 9:46 a.m. UTC | #2
On 06/24/2017 08:57 AM, Andreas Schwab wrote:
> On Jun 23 2017, fweimer@redhat.com (Florian Weimer) wrote:
> 
>>    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.  */
> 
> No need for size_t, it can only be 4 at most.

Should I change it to unsigned int?

Thanks,
Florian
diff mbox

Patch

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 = {