mirror of
https://github.com/curl/curl.git
synced 2025-02-17 14:59:45 +08:00
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.
This commit is contained in:
parent
3f9ab7cf5d
commit
9c94236e6c
@ -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
|
||||
|
50
lib/ftp.c
50
lib/ftp.c
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user