1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

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.
This commit is contained in:
Yang Tse 2010-11-23 21:38:20 +01:00
parent d212fe43af
commit 6fe18add71

View File

@ -118,12 +118,12 @@ Curl_getaddrinfo_ex(const char *nodename,
const struct addrinfo *hints, const struct addrinfo *hints,
Curl_addrinfo **result) Curl_addrinfo **result)
{ {
const struct addrinfo *ainext;
const struct addrinfo *ai; const struct addrinfo *ai;
struct addrinfo *aihead; struct addrinfo *aihead;
Curl_addrinfo *cafirst = NULL; Curl_addrinfo *cafirst = NULL;
Curl_addrinfo *calast = NULL; Curl_addrinfo *calast = NULL;
Curl_addrinfo *ca; Curl_addrinfo *ca;
size_t ss_size;
int error; int error;
*result = NULL; /* assume failure */ *result = NULL; /* assume failure */
@ -132,7 +132,28 @@ Curl_getaddrinfo_ex(const char *nodename,
if(error) if(error)
return 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) { if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
error = EAI_MEMORY; error = EAI_MEMORY;
@ -140,35 +161,28 @@ Curl_getaddrinfo_ex(const char *nodename,
} }
/* copy each structure member individually, member ordering, */ /* 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_flags = ai->ai_flags;
ca->ai_family = ai->ai_family; ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype; ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol; ca->ai_protocol = ai->ai_protocol;
ca->ai_addrlen = 0; ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL; ca->ai_addr = NULL;
ca->ai_canonname = NULL; ca->ai_canonname = NULL;
ca->ai_next = NULL; ca->ai_next = NULL;
if((ai->ai_addrlen > 0) && (ai->ai_addr != NULL)) { if((ca->ai_addr = malloc(ss_size)) == NULL) {
/* typecast below avoid warning on at least win64: error = EAI_MEMORY;
conversion from 'size_t' to 'curl_socklen_t', possible loss of data free(ca);
*/ break;
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);
} }
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(ai->ai_canonname != NULL) { if(ai->ai_canonname != NULL) {
if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
error = EAI_MEMORY; error = EAI_MEMORY;
if(ca->ai_addr) free(ca->ai_addr);
free(ca->ai_addr);
free(ca); free(ca);
break; break;
} }
@ -183,8 +197,6 @@ Curl_getaddrinfo_ex(const char *nodename,
calast->ai_next = ca; calast->ai_next = ca;
calast = ca; calast = ca;
/* fetch next element fom the addrinfo list */
ainext = ai->ai_next;
} }
/* destroy the addrinfo list */ /* destroy the addrinfo list */