diff options
Diffstat (limited to 'src/lib/net/inaddr.c')
-rw-r--r-- | src/lib/net/inaddr.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/src/lib/net/inaddr.c b/src/lib/net/inaddr.c index 1a2406ce5f..d50ac2440c 100644 --- a/src/lib/net/inaddr.c +++ b/src/lib/net/inaddr.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,7 +11,9 @@ #include "lib/net/inaddr.h" #include "lib/cc/torint.h" +#include "lib/container/smartlist.h" #include "lib/log/util_bug.h" +#include "lib/malloc/malloc.h" #include "lib/net/inaddr_st.h" #include "lib/string/compat_ctype.h" #include "lib/string/compat_string.h" @@ -35,12 +37,31 @@ * (Like inet_aton(str,addr), but works on Windows and Solaris.) */ int -tor_inet_aton(const char *str, struct in_addr* addr) +tor_inet_aton(const char *str, struct in_addr *addr) { - unsigned a,b,c,d; + unsigned a, b, c, d; char more; - if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4) + bool is_octal = false; + smartlist_t *sl = NULL; + + if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a, &b, &c, &d, &more) != 4) + return 0; + + /* Parse the octets and check them for leading zeros. */ + sl = smartlist_new(); + smartlist_split_string(sl, str, ".", 0, 0); + SMARTLIST_FOREACH(sl, const char *, octet, { + is_octal = (strlen(octet) > 1 && octet[0] == '0'); + if (is_octal) { + break; + } + }); + SMARTLIST_FOREACH(sl, char *, octet, tor_free(octet)); + smartlist_free(sl); + + if (is_octal) return 0; + if (a > 255) return 0; if (b > 255) return 0; if (c > 255) return 0; @@ -168,6 +189,13 @@ tor_inet_pton(int af, const char *src, void *dst) if (af == AF_INET) { return tor_inet_aton(src, dst); } else if (af == AF_INET6) { + ssize_t len = strlen(src); + + /* Reject if src has needless trailing ':'. */ + if (len > 2 && src[len - 1] == ':' && src[len - 2] != ':') { + return 0; + } + struct in6_addr *out = dst; uint16_t words[8]; int gapPos = -1, i, setWords=0; @@ -207,7 +235,6 @@ tor_inet_pton(int af, const char *src, void *dst) return 0; if (TOR_ISXDIGIT(*src)) { char *next; - ssize_t len; long r = strtol(src, &next, 16); if (next == NULL || next == src) { /* The 'next == src' error case can happen on versions of openbsd |