Commit 6fe18add authored by Yang Tse's avatar Yang Tse
Browse files

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.
parent d212fe43
Loading
Loading
Loading
Loading
+31 −19
Original line number Diff line number Diff line
@@ -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,34 +161,27 @@ 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) {
    if((ca->ai_addr = malloc(ss_size)) == 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((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
        error = EAI_MEMORY;
        if(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 */