Skip to content

Commit f923b27

Browse files
committed
Remove unnecessary sockaddr memory allocation
The size of sockaddr_in and sockaddr_in6 is known on compile-time and it is not that big for the stack.
1 parent cee33ba commit f923b27

File tree

1 file changed

+40
-48
lines changed

1 file changed

+40
-48
lines changed

main/network.c

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -825,88 +825,80 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
825825
for (sal = psal; !fatal && *sal != NULL; sal++) {
826826
sa = *sal;
827827

828-
/* create a socket for this address */
829-
sock = socket(sa->sa_family, socktype, 0);
830-
831-
if (sock == SOCK_ERR) {
832-
continue;
833-
}
834-
835828
switch (sa->sa_family) {
836829
#if HAVE_GETADDRINFO && HAVE_IPV6
837830
case AF_INET6:
838831
if (!bindto || strchr(bindto, ':')) {
839-
((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
840832
((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
841833
socklen = sizeof(struct sockaddr_in6);
842834
} else {
843-
socklen = 0;
844-
sa = NULL;
835+
/* Expect IPV4 address, skip to the next */
836+
continue;
845837
}
846838
break;
847839
#endif
848840
case AF_INET:
849-
((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
850841
((struct sockaddr_in *)sa)->sin_port = htons(port);
851842
socklen = sizeof(struct sockaddr_in);
843+
if (bindto && strchr(bindto, ':')) {
844+
/* IPV4 sock can not bind to IPV6 address */
845+
bindto = NULL;
846+
}
852847
break;
853848
default:
854-
/* Unknown family */
855-
socklen = 0;
856-
sa = NULL;
849+
/* Unsupported family, skip to the next */
850+
continue;
851+
}
852+
853+
/* create a socket for this address */
854+
sock = socket(sa->sa_family, socktype, 0);
855+
856+
if (sock == SOCK_ERR) {
857+
continue;
857858
}
858859

859860
if (sa) {
860861
/* make a connection attempt */
861862

862863
if (bindto) {
863-
struct sockaddr *local_address = NULL;
864-
int local_address_len = 0;
864+
struct {
865+
int len;
866+
union {
867+
struct sockaddr common;
868+
struct sockaddr_in in4;
869+
#if HAVE_IPV6 && HAVE_INET_PTON
870+
struct sockaddr_in6 in6;
871+
#endif
872+
};
873+
} local_address;
865874

875+
local_address.len = 0;
866876
if (sa->sa_family == AF_INET) {
867-
if (strchr(bindto,':')) {
868-
goto skip_bind;
869-
}
870-
struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
871-
872-
local_address = (struct sockaddr*)in4;
873-
local_address_len = sizeof(struct sockaddr_in);
874-
875-
in4->sin_family = sa->sa_family;
876-
in4->sin_port = htons(bindport);
877877
#ifdef HAVE_INET_PTON
878-
if (!inet_pton(AF_INET, bindto, &in4->sin_addr)) {
878+
if (inet_pton(AF_INET, bindto, &local_address.in4.sin_addr) == 1) {
879879
#else
880-
if (!inet_aton(bindto, &in4->sin_addr)) {
880+
if (inet_aton(bindto, &local_address.in4.sin_addr)) {
881881
#endif
882-
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
883-
goto skip_bind;
882+
local_address.len = sizeof(struct sockaddr_in);
883+
local_address.in4.sin_family = sa->sa_family;
884+
local_address.in4.sin_port = htons(bindport);
885+
memset(&(local_address.in4.sin_zero), 0, sizeof(local_address.in4.sin_zero));
884886
}
885-
memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
886887
}
887888
#if HAVE_IPV6 && HAVE_INET_PTON
888-
else { /* IPV6 */
889-
struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
890-
891-
local_address = (struct sockaddr*)in6;
892-
local_address_len = sizeof(struct sockaddr_in6);
893-
894-
in6->sin6_family = sa->sa_family;
895-
in6->sin6_port = htons(bindport);
896-
if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
897-
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
898-
goto skip_bind;
889+
else { /* IPV6 */
890+
if (inet_pton(AF_INET6, bindto, &local_address.in6.sin6_addr) == 1) {
891+
local_address.len = sizeof(struct sockaddr_in6);
892+
local_address.in6.sin6_family = sa->sa_family;
893+
local_address.in6.sin6_port = htons(bindport);
899894
}
900895
}
901896
#endif
902-
903-
if (!local_address || bind(sock, local_address, local_address_len)) {
897+
if (local_address.len == 0) {
898+
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
899+
} else if (bind(sock, &local_address.common, local_address.len)) {
904900
php_error_docref(NULL, E_WARNING, "Failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
905901
}
906-
skip_bind:
907-
if (local_address) {
908-
efree(local_address);
909-
}
910902
}
911903
/* free error string received during previous iteration (if any) */
912904
if (error_string && *error_string) {

0 commit comments

Comments
 (0)