diff options
| author | Marc Hoersken <info@marc-hoersken.de> | 2012-06-11 12:24:03 +0200 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2012-06-11 15:26:30 +0200 | 
| commit | 9c94236e6cc078a0dc5a78b6e2fefc1403e5375e (patch) | |
| tree | 15c4542b712a0ac9a000a86c6322cdf3a6575b16 /lib | |
| parent | 3f9ab7cf5deb892cc7b8cb3f36322e072898b789 (diff) | |
connect.c/ftp.c: Fixed dereferencing pointer breakin strict-aliasing
Fixed warning: dereferencing pointer does break strict-aliasing rules
by using a union instead of separate pointer variables.
Internal union sockaddr_u could probably be moved to generic header.
Thanks to Paul Howarth for the hint about using unions for this.
Important for winbuild: Separate declaration of sockaddr_u pointer.
The pointer variable *sock cannot be declared and initialized right
after the union declaration. Therefore it has to be a separate statement.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/connect.c | 38 | ||||
| -rw-r--r-- | lib/ftp.c | 50 | 
2 files changed, 49 insertions, 39 deletions
| diff --git a/lib/connect.c b/lib/connect.c index 42b626f1a..28c101930 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -253,12 +253,16 @@ static CURLcode bindlocal(struct connectdata *conn,    struct SessionHandle *data = conn->data;    struct Curl_sockaddr_storage sa; -  struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */    curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ -  struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; + +  union sockaddr_u { +    struct sockaddr sa; +    struct sockaddr_in sa4;  #ifdef ENABLE_IPV6 -  struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; +    struct sockaddr_in6 sa6;  #endif +  }; +  union sockaddr_u *sock = (union sockaddr_u *)&sa; /* bind to this address */    struct Curl_dns_entry *h=NULL;    unsigned short port = data->set.localport; /* use this port number, 0 for @@ -373,18 +377,18 @@ static CURLcode bindlocal(struct connectdata *conn,  #ifdef ENABLE_IPV6        /* ipv6 address */        if((af == AF_INET6) && -         (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { -        si6->sin6_family = AF_INET6; -        si6->sin6_port = htons(port); +         (Curl_inet_pton(AF_INET6, myhost, &sock->sa6.sin6_addr) > 0)) { +        sock->sa6.sin6_family = AF_INET6; +        sock->sa6.sin6_port = htons(port);          sizeof_sa = sizeof(struct sockaddr_in6);        }        else  #endif        /* ipv4 address */        if((af == AF_INET) && -         (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { -        si4->sin_family = AF_INET; -        si4->sin_port = htons(port); +         (Curl_inet_pton(AF_INET, myhost, &sock->sa4.sin_addr) > 0)) { +        sock->sa4.sin_family = AF_INET; +        sock->sa4.sin_port = htons(port);          sizeof_sa = sizeof(struct sockaddr_in);        }      } @@ -398,21 +402,21 @@ static CURLcode bindlocal(struct connectdata *conn,      /* no device was given, prepare sa to match af's needs */  #ifdef ENABLE_IPV6      if(af == AF_INET6) { -      si6->sin6_family = AF_INET6; -      si6->sin6_port = htons(port); +      sock->sa6.sin6_family = AF_INET6; +      sock->sa6.sin6_port = htons(port);        sizeof_sa = sizeof(struct sockaddr_in6);      }      else  #endif      if(af == AF_INET) { -      si4->sin_family = AF_INET; -      si4->sin_port = htons(port); +      sock->sa4.sin_family = AF_INET; +      sock->sa4.sin_port = htons(port);        sizeof_sa = sizeof(struct sockaddr_in);      }    }    for(;;) { -    if(bind(sockfd, sock, sizeof_sa) >= 0) { +    if(bind(sockfd, &sock->sa, sizeof_sa) >= 0) {        /* we succeeded to bind */        struct Curl_sockaddr_storage add;        curl_socklen_t size = sizeof(add); @@ -432,11 +436,11 @@ static CURLcode bindlocal(struct connectdata *conn,        infof(data, "Bind to local port %hu failed, trying next\n", port);        port++; /* try next port */        /* We re-use/clobber the port variable here below */ -      if(sock->sa_family == AF_INET) -        si4->sin_port = ntohs(port); +      if(sock->sa.sa_family == AF_INET) +        sock->sa4.sin_port = ntohs(port);  #ifdef ENABLE_IPV6        else -        si6->sin6_port = ntohs(port); +        sock->sa6.sin6_port = ntohs(port);  #endif      }      else @@ -955,14 +955,18 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,    char myhost[256] = "";    struct Curl_sockaddr_storage ss; +  union sockaddr_u { +    struct sockaddr sa; +    struct sockaddr_in sa4; +#ifdef ENABLE_IPV6 +    struct sockaddr_in6 sa6; +#endif +  }; +  union sockaddr_u *sock = (union sockaddr_u *)&ss; +    Curl_addrinfo *res, *ai;    curl_socklen_t sslen;    char hbuf[NI_MAXHOST]; -  struct sockaddr *sa=(struct sockaddr *)&ss; -  struct sockaddr_in * const sa4 = (void *)sa; -#ifdef ENABLE_IPV6 -  struct sockaddr_in6 * const sa6 = (void *)sa; -#endif    char tmp[1024];    static const char mode[][5] = { "EPRT", "PORT" };    int rc; @@ -1017,7 +1021,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,      else if((ip_end = strchr(string_ftpport, ':')) != NULL) {          /* either ipv6 or (ipv4|domain|interface):port(-range) */  #ifdef ENABLE_IPV6 -      if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { +      if(Curl_inet_pton(AF_INET6, string_ftpport, &sock->sa6) == 1) {          /* ipv6 */          port_min = port_max = 0;          strcpy(addr, string_ftpport); @@ -1073,20 +1077,22 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,         the IP from the control connection */      sslen = sizeof(ss); -    if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { +    if(getsockname(conn->sock[FIRSTSOCKET], &sock->sa, &sslen)) {        failf(data, "getsockname() failed: %s",            Curl_strerror(conn, SOCKERRNO) );        Curl_safefree(addr);        return CURLE_FTP_PORT_FAILED;      } -    switch(sa->sa_family) { +    switch(sock->sa.sa_family) {  #ifdef ENABLE_IPV6      case AF_INET6: -      Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); +      Curl_inet_ntop(sock->sa.sa_family, &sock->sa6.sin6_addr, hbuf, +                     sizeof(hbuf));        break;  #endif      default: -      Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); +      Curl_inet_ntop(sock->sa.sa_family, &sock->sa4.sin_addr, hbuf, +                     sizeof(hbuf));        break;      }      host = hbuf; /* use this host name */ @@ -1134,18 +1140,18 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,    /* step 3, bind to a suitable local address */ -  memcpy(sa, ai->ai_addr, ai->ai_addrlen); +  memcpy(&sock->sa, ai->ai_addr, ai->ai_addrlen);    sslen = ai->ai_addrlen;    for(port = port_min; port <= port_max;) { -    if(sa->sa_family == AF_INET) -      sa4->sin_port = htons(port); +    if(sock->sa.sa_family == AF_INET) +      sock->sa4.sin_port = htons(port);  #ifdef ENABLE_IPV6      else -      sa6->sin6_port = htons(port); +      sock->sa6.sin6_port = htons(port);  #endif      /* Try binding the given address. */ -    if(bind(portsock, sa, sslen) ) { +    if(bind(portsock, &sock->sa, sslen) ) {        /* It failed. */        error = SOCKERRNO;        if(possibly_non_local && (error == EADDRNOTAVAIL)) { @@ -1157,7 +1163,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,                Curl_strerror(conn, error) );          sslen = sizeof(ss); -        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { +        if(getsockname(conn->sock[FIRSTSOCKET], &sock->sa, &sslen)) {            failf(data, "getsockname() failed: %s",                  Curl_strerror(conn, SOCKERRNO) );            Curl_closesocket(conn, portsock); @@ -1190,7 +1196,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,    /* get the name again after the bind() so that we can extract the       port number it uses now */    sslen = sizeof(ss); -  if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { +  if(getsockname(portsock, (struct sockaddr *)&sock->sa, &sslen)) {      failf(data, "getsockname() failed: %s",            Curl_strerror(conn, SOCKERRNO) );      Curl_closesocket(conn, portsock); @@ -1224,17 +1230,17 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,        /* if disabled, goto next */        continue; -    if((PORT == fcmd) && sa->sa_family != AF_INET) +    if((PORT == fcmd) && sock->sa.sa_family != AF_INET)        /* PORT is ipv4 only */        continue; -    switch (sa->sa_family) { +    switch (sock->sa.sa_family) {      case AF_INET: -      port = ntohs(sa4->sin_port); +      port = ntohs(sock->sa4.sin_port);        break;  #ifdef ENABLE_IPV6      case AF_INET6: -      port = ntohs(sa6->sin6_port); +      port = ntohs(sock->sa6.sin6_port);        break;  #endif      default: @@ -1251,7 +1257,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,         */        result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], -                             sa->sa_family == AF_INET?1:2, +                             sock->sa.sa_family == AF_INET?1:2,                               myhost, port);        if(result) {          failf(data, "Failure sending EPRT command: %s", | 
