summaryrefslogtreecommitdiff
path: root/resolv/inet_addr.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-10-02 16:34:45 +0000
committerUlrich Drepper <drepper@redhat.com>1999-10-02 16:34:45 +0000
commit81ca53df7dea9967eeb56d47376e0f3fd2c9edda (patch)
tree4a2fb76f4990141862cc43093c2cc7e1fab56d04 /resolv/inet_addr.c
parenta465f6bdd2a7a1f79083fec65c3eeff093451e9e (diff)
Update.
1999-10-02 Ulrich Drepper <drepper@cygnus.com> * resolv/tst-aton.c (main): Add more tests. * resolv/inet_addr.c (inet_aton): Correct some problems with to large numbers. Optimize a bit.
Diffstat (limited to 'resolv/inet_addr.c')
-rw-r--r--resolv/inet_addr.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
index d9b37015b3..e7f56d4588 100644
--- a/resolv/inet_addr.c
+++ b/resolv/inet_addr.c
@@ -60,6 +60,8 @@ static char rcsid[] = "$Id$";
#include <arpa/inet.h>
#include <ctype.h>
#ifdef _LIBC
+# include <endian.h>
+# include <stdint.h>
# include <stdlib.h>
# include <limits.h>
# include <errno.h>
@@ -100,17 +102,24 @@ inet_aton(cp, addr)
#ifndef _LIBC
register int base;
#endif
- register int n;
register char c;
- u_int32_t parts[4];
- register u_int32_t *pp = parts;
+ union iaddr {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ register uint8_t *pp = res.bytes;
+#else
+ register uint8_t *pp = &res.bytes[4];
+#endif
+ int digit;
#ifdef _LIBC
int saved_errno = errno;
__set_errno (0);
#endif
- memset (parts, '\0', sizeof (parts));
+ res.word = 0;
c = *cp;
for (;;) {
@@ -123,12 +132,15 @@ inet_aton(cp, addr)
goto ret_0;
#ifdef _LIBC
{
- unsigned long ul = strtoul (cp, (char **) &cp, 0);
+ char *endp;
+ unsigned long ul = strtoul (cp, (char **) &endp, 0);
if (ul == ULONG_MAX && errno == ERANGE)
goto ret_0;
if (ul > 0xfffffffful)
goto ret_0;
val = ul;
+ digit = cp != endp;
+ cp = endp;
}
c = *cp;
#else
@@ -160,9 +172,17 @@ inet_aton(cp, addr)
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
- if (pp >= parts + 3)
+ if ((BYTE_ORDER == LITTLE_ENDIAN
+ && pp >= res.bytes + 3)
+ || (BYTE_ORDER == BIG_ENDIAN
+ && pp == res.bytes)
+ || val > 0xff)
goto ret_0;
+#if BYTE_ORDER == LITTLE_ENDIAN
*pp++ = val;
+#else
+ *--pp = val;
+#endif
c = *++cp;
} else
break;
@@ -172,21 +192,21 @@ inet_aton(cp, addr)
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
goto ret_0;
+
/*
- * Concoct the address according to
- * the number of parts specified.
+ * Did we get a valid digit?
*/
- n = pp - parts + 1;
+ if (!digit)
+ goto ret_0;
- if (n == 0 /* initial nondigit */
- || parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff
- || val > max[n - 1])
+ /* Check whether the last part is in its limits depending on
+ the number of parts in total. */
+ if ((BYTE_ORDER == LITTLE_ENDIAN && val > max[pp - res.bytes])
+ || (BYTE_ORDER == BIG_ENDIAN && val > max[res.bytes - pp]))
goto ret_0;
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-
if (addr)
- addr->s_addr = htonl(val);
+ addr->s_addr = res.word | htonl (val);
#ifdef _LIBC
__set_errno (saved_errno);