]> granicus.if.org Git - curl/commitdiff
Curl_getaddrinfo_ex: sanitize function results.
authorYang Tse <yangsita@gmail.com>
Tue, 23 Nov 2010 20:38:20 +0000 (21:38 +0100)
committerYang Tse <yangsita@gmail.com>
Tue, 23 Nov 2010 20:38:20 +0000 (21:38 +0100)
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.

lib/curl_addrinfo.c

index cfb858c6bdd321585f8738a3b9c5a93605a0fe43..7fb816f3a2ed7948eed895343949c047d94de345 100644 (file)
@@ -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 */