ares_inet_net_pton: fix non-rejection of some malformed literals
authorYang Tse <yangsita@gmail.com>
Wed, 15 Dec 2010 01:44:07 +0000 (02:44 +0100)
committerYang Tse <yangsita@gmail.com>
Wed, 15 Dec 2010 01:44:07 +0000 (02:44 +0100)
ares_inet_net_pton would return wrong values when excessively large,
and invalid, netmasks are used. Fixes are from bind-9.5.3rc1,
issue also described in the WLB-2008080064 advisory.

CHANGES
RELEASE-NOTES
inet_net_pton.c

diff --git a/CHANGES b/CHANGES
index 5862710b62226c8368a691f1c2be717f7a4a07fb..e4746f9719171d02e3f4255e022467d386e12fe6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,7 @@ Fixed:
 
  o detection of semicolon comments in resolv.conf
  o avoid using system's inet_net_pton affected by the WLB-2008080064 advisory
+ o replacement ares_inet_net_pton affected by the WLB-2008080064 advisory
 
 Version 1.7.4 (December 9, 2010)
 
index d0e5494c15490f49bdaa34559c11ece060c4a0e1..3d6ba3acb2cabd86b39908e0e5d87c8db84b680d 100644 (file)
@@ -8,6 +8,7 @@ Fixed:
 
  o detection of semicolon comments in resolv.conf
  o avoid using system's inet_net_pton affected by the WLB-2008080064 advisory
+ o replacement ares_inet_net_pton affected by the WLB-2008080064 advisory
 
 Thanks go to these friendly people for their efforts and contributions:
 
index d9165e740fb4c127876694270f27134ea10ae71e..9bbe7aa19b532ab186f1da9c04e2794c7d49ab88 100644 (file)
@@ -83,13 +83,14 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
 
   ch = *src++;
   if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+      && ISASCII(src[1])
       && ISXDIGIT(src[1])) {
     /* Hexadecimal: Eat nybble string. */
     if (!size)
       goto emsgsize;
     dirty = 0;
     src++;  /* skip x or X. */
-    while ((ch = *src++) != '\0' && ISXDIGIT(ch)) {
+    while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) {
       if (ISUPPER(ch))
         ch = tolower(ch);
       n = (int)(strchr(xdigits, ch) - xdigits);
@@ -109,7 +110,7 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
         goto emsgsize;
       *dst++ = (unsigned char) (tmp << 4);
     }
-  } else if (ISDIGIT(ch)) {
+  } else if (ISASCII(ch) && ISDIGIT(ch)) {
     /* Decimal: eat dotted digit string. */
     for (;;) {
       tmp = 0;
@@ -120,7 +121,7 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
         if (tmp > 255)
           goto enoent;
       } while ((ch = *src++) != '\0' &&
-               ISDIGIT(ch));
+               ISASCII(ch) && ISDIGIT(ch));
       if (!size--)
         goto emsgsize;
       *dst++ = (unsigned char) tmp;
@@ -129,14 +130,14 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
       if (ch != '.')
         goto enoent;
       ch = *src++;
-      if (!ISDIGIT(ch))
+      if (!ISASCII(ch) || !ISDIGIT(ch))
         goto enoent;
     }
   } else
     goto enoent;
 
   bits = -1;
-  if (ch == '/' &&
+  if (ch == '/' && ISASCII(src[0]) &&
       ISDIGIT(src[0]) && dst > odst) {
     /* CIDR width specifier.  Nothing can follow it. */
     ch = *src++;    /* Skip over the /. */
@@ -145,11 +146,11 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
       n = (int)(strchr(digits, ch) - digits);
       bits *= 10;
       bits += n;
-    } while ((ch = *src++) != '\0' && ISDIGIT(ch));
+      if (bits > 32)
+        goto enoent;
+    } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
     if (ch != '\0')
       goto enoent;
-    if (bits > 32)
-      goto emsgsize;
   }
 
   /* Firey death and destruction unless we prefetched EOS. */
@@ -447,4 +448,4 @@ int ares_inet_pton(int af, const char *src, void *dst)
     return 0;
   return (result > -1 ? 1 : -1);
 }
-#endif /* HAVE_INET_PTON */
+#endif