From e65bdafbe3e32bf03b1b1acdb5a0672ef97e79c9 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 12 Jan 2011 21:48:07 +0000 Subject: Fix url_host_is_ip_address() when encountering blatently invalid IPv4 addresses (which inet_aton fails to notice). Also fix a number of insidious buffer overflows. svn path=/trunk/netsurf/; revision=11293 --- utils/url.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'utils/url.c') diff --git a/utils/url.c b/utils/url.c index 67b9f7d41..e00f43824 100644 --- a/utils/url.c +++ b/utils/url.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -91,7 +90,7 @@ void url_init(void) bool url_host_is_ip_address(const char *host) { struct in_addr ipv4; - size_t z = strlen(host); + size_t host_len = strlen(host); const char *sane_host; const char *slash; #ifndef NO_IPV6 @@ -116,28 +115,46 @@ bool url_host_is_ip_address(const char *host) * -- rjek - 2010-11-04 */ - slash = index(host, '/'); + slash = strchr(host, '/'); if (slash == NULL) { sane_host = host; } else { char *c = strdup(host); c[slash - host] = '\0'; sane_host = c; - LOG(("WARNING: called with non-host '%s'", - host)); + host_len = slash - host - 1; + LOG(("WARNING: called with non-host '%s'", host)); } - if (strspn(sane_host, "0123456789abcdefABCDEF[].:") < z) + if (strspn(sane_host, "0123456789abcdefABCDEF[].:") < host_len) goto out_false; - if (inet_aton(sane_host, &ipv4) != 0) - goto out_true; + if (inet_aton(sane_host, &ipv4) != 0) { + /* This can only be a sane IPv4 address if it contains 3 dots. + * Helpfully, inet_aton is happy to treat "a", "a.b", "a.b.c", + * and "a.b.c.d" as valid IPv4 address strings where we only + * support the full, dotted-quad, form. + */ + int num_dots = 0; + size_t index; + + for (index = 0; index < host_len; index++) { + if (sane_host[index] == '.') + num_dots++; + } + + if (num_dots == 3) + goto out_true; + else + goto out_false; + } + #ifndef NO_IPV6 - if (sane_host[0] != '[' || sane_host[z] != ']') + if (sane_host[0] != '[' || sane_host[host_len] != ']') goto out_false; strncpy(ipv6_addr, sane_host + 1, sizeof(ipv6_addr)); - ipv6_addr[z - 1] = '\0'; + ipv6_addr[sizeof(ipv6_addr) - 1] = '\0'; if (inet_pton(AF_INET6, ipv6_addr, &ipv6) == 1) goto out_true; -- cgit v1.2.3