diff options
author | Yang Tse <yangsita@gmail.com> | 2010-11-23 21:38:20 +0100 |
---|---|---|
committer | Yang Tse <yangsita@gmail.com> | 2010-11-23 21:38:20 +0100 |
commit | 6fe18add714d3d56d4ba24f2a2463fca125c0a1b (patch) | |
tree | 7f512fec09cab37784412498ca0a72afaa2b7059 /lib/curl_addrinfo.c | |
parent | d212fe43af25b9d550cf7e84b24374a3ea120808 (diff) | |
download | curl-6fe18add714d3d56d4ba24f2a2463fca125c0a1b.tar.gz |
Curl_getaddrinfo_ex: sanitize function results.
Ensure that spurious results from system's getaddrinfo() ares not propagated
by Curl_getaddrinfo_ex() into the library.
Also ensure that the ai_addrlen member of Curl_getaddrinfo_ex()'s output linked
list of Curl_addrinfo structures has appropriate family-specific address size.
Diffstat (limited to 'lib/curl_addrinfo.c')
-rw-r--r-- | lib/curl_addrinfo.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index cfb858c6b..7fb816f3a 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -118,12 +118,12 @@ Curl_getaddrinfo_ex(const char *nodename, const struct addrinfo *hints, Curl_addrinfo **result) { - const struct addrinfo *ainext; const struct addrinfo *ai; struct addrinfo *aihead; Curl_addrinfo *cafirst = NULL; Curl_addrinfo *calast = NULL; Curl_addrinfo *ca; + size_t ss_size; int error; *result = NULL; /* assume failure */ @@ -132,7 +132,28 @@ Curl_getaddrinfo_ex(const char *nodename, if(error) return error; - for(ai = aihead; ai != NULL; ai = ainext) { + /* traverse the addrinfo list */ + + for(ai = aihead; ai != NULL; ai = ai->ai_next) { + + /* ignore elements with unsupported address family, */ + /* settle family-specific sockaddr structure size. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) { error = EAI_MEMORY; @@ -140,35 +161,28 @@ Curl_getaddrinfo_ex(const char *nodename, } /* copy each structure member individually, member ordering, */ - /* size, or padding might be different for each structure. */ + /* size, or padding might be different for each platform. */ ca->ai_flags = ai->ai_flags; ca->ai_family = ai->ai_family; ca->ai_socktype = ai->ai_socktype; ca->ai_protocol = ai->ai_protocol; - ca->ai_addrlen = 0; + ca->ai_addrlen = (curl_socklen_t)ss_size; ca->ai_addr = NULL; ca->ai_canonname = NULL; ca->ai_next = NULL; - if((ai->ai_addrlen > 0) && (ai->ai_addr != NULL)) { - /* typecast below avoid warning on at least win64: - conversion from 'size_t' to 'curl_socklen_t', possible loss of data - */ - ca->ai_addrlen = (curl_socklen_t)ai->ai_addrlen; - if((ca->ai_addr = malloc(ca->ai_addrlen)) == NULL) { - error = EAI_MEMORY; - free(ca); - break; - } - memcpy(ca->ai_addr, ai->ai_addr, ca->ai_addrlen); + if((ca->ai_addr = malloc(ss_size)) == NULL) { + error = EAI_MEMORY; + free(ca); + break; } + memcpy(ca->ai_addr, ai->ai_addr, ss_size); if(ai->ai_canonname != NULL) { if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { error = EAI_MEMORY; - if(ca->ai_addr) - free(ca->ai_addr); + free(ca->ai_addr); free(ca); break; } @@ -183,8 +197,6 @@ Curl_getaddrinfo_ex(const char *nodename, calast->ai_next = ca; calast = ca; - /* fetch next element fom the addrinfo list */ - ainext = ai->ai_next; } /* destroy the addrinfo list */ |