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
This commit is contained in:
John Mark Bell 2011-01-12 21:48:07 +00:00
parent b58dcc351f
commit e65bdafbe3

View File

@ -28,7 +28,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <regex.h> #include <regex.h>
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -91,7 +90,7 @@ void url_init(void)
bool url_host_is_ip_address(const char *host) bool url_host_is_ip_address(const char *host)
{ {
struct in_addr ipv4; struct in_addr ipv4;
size_t z = strlen(host); size_t host_len = strlen(host);
const char *sane_host; const char *sane_host;
const char *slash; const char *slash;
#ifndef NO_IPV6 #ifndef NO_IPV6
@ -116,28 +115,46 @@ bool url_host_is_ip_address(const char *host)
* -- rjek - 2010-11-04 * -- rjek - 2010-11-04
*/ */
slash = index(host, '/'); slash = strchr(host, '/');
if (slash == NULL) { if (slash == NULL) {
sane_host = host; sane_host = host;
} else { } else {
char *c = strdup(host); char *c = strdup(host);
c[slash - host] = '\0'; c[slash - host] = '\0';
sane_host = c; sane_host = c;
LOG(("WARNING: called with non-host '%s'", host_len = slash - host - 1;
host)); LOG(("WARNING: called with non-host '%s'", host));
} }
if (strspn(sane_host, "0123456789abcdefABCDEF[].:") < z) if (strspn(sane_host, "0123456789abcdefABCDEF[].:") < host_len)
goto out_false; goto out_false;
if (inet_aton(sane_host, &ipv4) != 0) if (inet_aton(sane_host, &ipv4) != 0) {
goto out_true; /* 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 #ifndef NO_IPV6
if (sane_host[0] != '[' || sane_host[z] != ']') if (sane_host[0] != '[' || sane_host[host_len] != ']')
goto out_false; goto out_false;
strncpy(ipv6_addr, sane_host + 1, sizeof(ipv6_addr)); 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) if (inet_pton(AF_INET6, ipv6_addr, &ipv6) == 1)
goto out_true; goto out_true;