about summary refs log tree commit diff
path: root/resolv/inet_net_pton.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/inet_net_pton.c')
-rw-r--r--resolv/inet_net_pton.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/resolv/inet_net_pton.c b/resolv/inet_net_pton.c
index 7c863492d7..bf6fe02ed8 100644
--- a/resolv/inet_net_pton.c
+++ b/resolv/inet_net_pton.c
@@ -97,9 +97,7 @@ inet_net_pton_ipv4(src, dst, size)
 	int n, ch, tmp, dirty, bits;
 	const u_char *odst = dst;
 
-	bits = -1;
 	ch = *src++;
-
 	if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
 	    && isascii(src[1]) && isxdigit(src[1])) {
 		/* Hexadecimal: Eat nybble string. */
@@ -150,6 +148,7 @@ inet_net_pton_ipv4(src, dst, size)
 	} else
 		goto enoent;
 
+	bits = -1;
 	if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
 		/* CIDR width specifier.  Nothing can follow it. */
 		ch = *src++;	/* Skip over the /. */
@@ -163,6 +162,8 @@ inet_net_pton_ipv4(src, dst, size)
 			 isascii(ch) && isdigit(ch));
 		if (ch != '\0')
 			goto enoent;
+		if (bits > 32)
+			goto emsgsize;
 	}
 
 	/* Firey death and destruction unless we prefetched EOS. */
@@ -174,14 +175,19 @@ inet_net_pton_ipv4(src, dst, size)
 		goto enoent;
 	/* If no CIDR spec was given, infer width from net class. */
 	if (bits == -1) {
-		if (*odst >= 224)
+		if (*odst >= 240)	/* Class E */
+			bits = 32;
+		else if (*odst >= 224)	/* Class D */
 			bits = 4;
-		else if (*odst >= 192)
+		else if (*odst >= 192)	/* Class C */
 			bits = 24;
-		else if (*odst >= 128)
+		else if (*odst >= 128)	/* Class B */
 			bits = 16;
-		else
+		else			/* Class A */
 			bits = 8;
+		/* If imputed mask is narrower than specified octets, widen. */
+		if (bits >= 8 && bits < ((dst - odst) * 8))
+			bits = (dst - odst) * 8;
 	}
 	/* Extend network to cover the actual mask. */
 	while (bits > ((dst - odst) * 8)) {