Skip to content

Commit cf1a979

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 cf1a979

File tree

1 file changed

+40
-46
lines changed

1 file changed

+40
-46
lines changed

main/network.c

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -825,13 +825,6 @@ 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:
@@ -840,73 +833,74 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
840833
((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
841834
socklen = sizeof(struct sockaddr_in6);
842835
} else {
843-
socklen = 0;
844-
sa = NULL;
836+
/* Expect IPV4 address, skip to the next */
837+
continue;
845838
}
846839
break;
847840
#endif
848841
case AF_INET:
849842
((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
850843
((struct sockaddr_in *)sa)->sin_port = htons(port);
851844
socklen = sizeof(struct sockaddr_in);
845+
if (strchr(bindto, ':')) {
846+
/* IPV4 sock can not bind to IPV6 address */
847+
bindto = NULL;
848+
}
852849
break;
853850
default:
854-
/* Unknown family */
855-
socklen = 0;
856-
sa = NULL;
851+
/* Unsupported family, skip to the next */
852+
continue;
853+
}
854+
855+
/* create a socket for this address */
856+
sock = socket(sa->sa_family, socktype, 0);
857+
858+
if (sock == SOCK_ERR) {
859+
continue;
857860
}
858861

859862
if (sa) {
860863
/* make a connection attempt */
861864

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

877+
local_address.len = 0;
866878
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);
877879
#ifdef HAVE_INET_PTON
878-
if (!inet_pton(AF_INET, bindto, &in4->sin_addr)) {
880+
if (inet_pton(AF_INET, bindto, &local_address.in4.sin_addr) == 1) {
879881
#else
880-
if (!inet_aton(bindto, &in4->sin_addr)) {
882+
if (inet_aton(bindto, &local_address.in4.sin_addr)) {
881883
#endif
882-
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
883-
goto skip_bind;
884+
local_address.len = sizeof(struct sockaddr_in);
885+
local_address.in4.sin_family = sa->sa_family;
886+
local_address.in4.sin_port = htons(bindport);
887+
memset(&(local_address.in4.sin_zero), 0, sizeof(local_address.in4.sin_zero));
884888
}
885-
memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
886889
}
887890
#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;
891+
else { /* IPV6 */
892+
if (inet_pton(AF_INET6, bindto, &local_address.in6.sin6_addr) == 1) {
893+
local_address.len = sizeof(struct sockaddr_in6);
894+
local_address.in6.sin6_family = sa->sa_family;
895+
local_address.in6.sin6_port = htons(bindport);
899896
}
900897
}
901898
#endif
902-
903-
if (!local_address || bind(sock, local_address, local_address_len)) {
899+
if (local_address.len == 0) {
900+
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
901+
} else if (bind(sock, &local_address.common, local_address.len)) {
904902
php_error_docref(NULL, E_WARNING, "Failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
905903
}
906-
skip_bind:
907-
if (local_address) {
908-
efree(local_address);
909-
}
910904
}
911905
/* free error string received during previous iteration (if any) */
912906
if (error_string && *error_string) {

0 commit comments

Comments
 (0)