summaryrefslogtreecommitdiff
path: root/lib/curl_addrinfo.c
diff options
context:
space:
mode:
authorYang Tse <yangsita@gmail.com>2010-11-23 21:38:20 +0100
committerYang Tse <yangsita@gmail.com>2010-11-23 21:38:20 +0100
commit6fe18add714d3d56d4ba24f2a2463fca125c0a1b (patch)
tree7f512fec09cab37784412498ca0a72afaa2b7059 /lib/curl_addrinfo.c
parentd212fe43af25b9d550cf7e84b24374a3ea120808 (diff)
downloadcurl-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.c50
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 */