diff options
author | Mike Frysinger <vapier@gentoo.org> | 2007-09-15 08:12:15 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2007-09-15 08:12:15 +0000 |
commit | b5a7ad59209216ead9ded5b2cd69ac5e0dd63d2c (patch) | |
tree | 806e068d96eb4bc6f2bf0c8b319456194bac90a4 /libc | |
parent | b9a82d5b22c68a57e6a9fa51cc4d1ec507f266a5 (diff) |
switch to a smaller/more robust implementation by Andrey Simonenko and as suggested by Natanael Copa
harvested from: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/92880
Diffstat (limited to 'libc')
-rw-r--r-- | libc/inet/inet_net.c | 84 |
1 files changed, 41 insertions, 43 deletions
diff --git a/libc/inet/inet_net.c b/libc/inet/inet_net.c index f8148c274..51edcf212 100644 --- a/libc/inet/inet_net.c +++ b/libc/inet/inet_net.c @@ -37,6 +37,7 @@ #include <ctype.h> #include <netinet/in.h> #include <arpa/inet.h> + #ifdef __UCLIBC_HAS_XLOCALE__ libc_hidden_proto(__ctype_b_loc) #elif __UCLIBC_HAS_CTYPE_TABLES__ @@ -52,57 +53,54 @@ libc_hidden_proto(inet_network) in_addr_t inet_network(const char *cp) { - register in_addr_t val, base, n; - register char c; - in_addr_t parts[4], *pp = parts; - register unsigned int i; + u_char c; + int got_data; + u_int base, dots; + in_addr_t res, val; -again: - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, other=decimal. - */ - val = 0; base = 10; - /* - * The 4.4BSD version of this file also accepts 'x__' as a hexa - * number. I don't think this is correct. -- Uli - */ + res = 0; + dots = 0; + again: + val = 0; + got_data = 0; if (*cp == '0') { - if (*++cp == 'x' || *cp == 'X') - base = 16, cp++; - else - base = 8; - } - while ((c = *cp)) { - if (isdigit(c)) { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isxdigit(c)) { - val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + if (*cp == 'x' || *cp == 'X') { cp++; - continue; + base = 16; + } else { + base = 8; + got_data = 1; } - break; + } else + base = 10; + while ((c = *cp) != '\0') { + if (isdigit(c)) { + if (base == 8 && c > '7') + return (INADDR_NONE); + val = val * base + c - '0'; + } else if (base == 16 && isxdigit(c)) + val = (val << 4) + 10 - (islower(c) ? 'a' : 'A'); + else + break; + if (val > 0xff) + return (INADDR_NONE); + cp++; + got_data = 1; } - if (*cp == '.') { - if (pp >= parts + 4) + if (!got_data) + return (INADDR_NONE); + if (dots != 0) + res <<= 8; + res |= val; + if (c == '.') { + if (++dots == 4) return (INADDR_NONE); - *pp++ = val, cp++; + cp++; goto again; } - if (*cp && !isspace(*cp)) - return (INADDR_NONE); - *pp++ = val; - n = pp - parts; - if (n > 4) + if (c != '\0') return (INADDR_NONE); - for (val = 0, i = 0; i < n; i++) { - val <<= 8; - val |= parts[i] & 0xff; - } - return (val); + return (res); } libc_hidden_def(inet_network) |