Skip to content

Commit 36e1406

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 36e1406

File tree

1 file changed

+49
-60
lines changed

1 file changed

+49
-60
lines changed

main/network.c

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -430,30 +430,27 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
430430
for (sal = psal; *sal != NULL; sal++) {
431431
sa = *sal;
432432

433-
/* create a socket for this address */
434-
sock = socket(sa->sa_family, socktype, 0);
435-
436-
if (sock == SOCK_ERR) {
437-
continue;
438-
}
439-
440433
switch (sa->sa_family) {
441434
#if HAVE_GETADDRINFO && HAVE_IPV6
442435
case AF_INET6:
443-
((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
444436
((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
445437
socklen = sizeof(struct sockaddr_in6);
446438
break;
447439
#endif
448440
case AF_INET:
449-
((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
450441
((struct sockaddr_in *)sa)->sin_port = htons(port);
451442
socklen = sizeof(struct sockaddr_in);
452443
break;
453444
default:
454-
/* Unknown family */
455-
socklen = 0;
456-
sa = NULL;
445+
/* Unsupported family, skip to the next */
446+
continue;
447+
}
448+
449+
/* create a socket for this address */
450+
sock = socket(sa->sa_family, socktype, 0);
451+
452+
if (sock == SOCK_ERR) {
453+
continue;
457454
}
458455

459456
if (sa) {
@@ -825,88 +822,80 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
825822
for (sal = psal; !fatal && *sal != NULL; sal++) {
826823
sa = *sal;
827824

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-
835825
switch (sa->sa_family) {
836826
#if HAVE_GETADDRINFO && HAVE_IPV6
837827
case AF_INET6:
838828
if (!bindto || strchr(bindto, ':')) {
839-
((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
840829
((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
841830
socklen = sizeof(struct sockaddr_in6);
842831
} else {
843-
socklen = 0;
844-
sa = NULL;
832+
/* Expect IPV4 address, skip to the next */
833+
continue;
845834
}
846835
break;
847836
#endif
848837
case AF_INET:
849-
((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
850838
((struct sockaddr_in *)sa)->sin_port = htons(port);
851839
socklen = sizeof(struct sockaddr_in);
840+
if (bindto && strchr(bindto, ':')) {
841+
/* IPV4 sock can not bind to IPV6 address */
842+
bindto = NULL;
843+
}
852844
break;
853845
default:
854-
/* Unknown family */
855-
socklen = 0;
856-
sa = NULL;
846+
/* Unsupported family, skip to the next */
847+
continue;
848+
}
849+
850+
/* create a socket for this address */
851+
sock = socket(sa->sa_family, socktype, 0);
852+
853+
if (sock == SOCK_ERR) {
854+
continue;
857855
}
858856

859857
if (sa) {
860858
/* make a connection attempt */
861859

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

872+
local_address.len = 0;
866873
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);
877874
#ifdef HAVE_INET_PTON
878-
if (!inet_pton(AF_INET, bindto, &in4->sin_addr)) {
875+
if (inet_pton(AF_INET, bindto, &local_address.in4.sin_addr) == 1) {
879876
#else
880-
if (!inet_aton(bindto, &in4->sin_addr)) {
877+
if (inet_aton(bindto, &local_address.in4.sin_addr)) {
881878
#endif
882-
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
883-
goto skip_bind;
879+
local_address.len = sizeof(struct sockaddr_in);
880+
local_address.in4.sin_family = sa->sa_family;
881+
local_address.in4.sin_port = htons(bindport);
882+
memset(&(local_address.in4.sin_zero), 0, sizeof(local_address.in4.sin_zero));
884883
}
885-
memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
886884
}
887885
#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;
886+
else { /* IPV6 */
887+
if (inet_pton(AF_INET6, bindto, &local_address.in6.sin6_addr) == 1) {
888+
local_address.len = sizeof(struct sockaddr_in6);
889+
local_address.in6.sin6_family = sa->sa_family;
890+
local_address.in6.sin6_port = htons(bindport);
899891
}
900892
}
901893
#endif
902-
903-
if (!local_address || bind(sock, local_address, local_address_len)) {
894+
if (local_address.len == 0) {
895+
php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
896+
} else if (bind(sock, &local_address.common, local_address.len)) {
904897
php_error_docref(NULL, E_WARNING, "Failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
905898
}
906-
skip_bind:
907-
if (local_address) {
908-
efree(local_address);
909-
}
910899
}
911900
/* free error string received during previous iteration (if any) */
912901
if (error_string && *error_string) {

0 commit comments

Comments
 (0)