Skip to content

Fix #80067: Omitting the port in bindto setting errors #6104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ext/standard/tests/network/bindto.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ $fp = stream_socket_client(
);
?>
--EXPECTF--
Warning: stream_socket_client(): unable to connect to tcp://%s:80 (Failed to parse address "invalid") in %s on line %d
Warning: stream_socket_client(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d

Warning: stream_socket_client(): unable to connect to tcp://www.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.com:80 (php_network_getaddresses: getaddrinfo failed: %s) in %s on line %d
13 changes: 13 additions & 0 deletions ext/standard/tests/network/bug80067.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Bug #80067 (Omitting the port in bindto setting errors)
--SKIPIF--
<?php
if (getenv("SKIP_ONLINE_TESTS")) die('skip online test');
?>
--FILE--
<?php
$context = stream_context_create(['socket' => ['bindto' => '0']]);
var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false);
?>
--EXPECT--
bool(true)
12 changes: 12 additions & 0 deletions main/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka

if ((n = getaddrinfo(host, NULL, &hints, &res))) {
if (error_string) {
/* free error string received during previous iteration (if any) */
if (*error_string) {
zend_string_release_ex(*error_string, 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it feasible to push this up into the caller? It seems somewhat odd to deal with it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes are all in php_network_getaddresses() which is exported. We could fix all calls from core and bundled extensions, but external extensions may have the same memory leak.

Also note that I copied that snippet from php_network_connect_socket_to_host(), and that had been introduced with 79d649e (which fixed a similar memory leak long ago).

Maybe leave it this way for PHP 7, and push up into the caller for PHP 8?

*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
} else {
Expand All @@ -208,6 +212,10 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
return 0;
} else if (res == NULL) {
if (error_string) {
/* free error string received during previous iteration (if any) */
if (*error_string) {
zend_string_release_ex(*error_string, 0);
}
*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
} else {
Expand Down Expand Up @@ -241,6 +249,10 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
}
if (host_info == NULL) {
if (error_string) {
/* free error string received during previous iteration (if any) */
if (*error_string) {
zend_string_release_ex(*error_string, 0);
}
*error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
} else {
Expand Down
4 changes: 0 additions & 4 deletions main/streams/xp_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,6 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_
return -1;
}
bindto = parse_ip_address_ex(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval), &bindport, xparam->want_errortext, &xparam->outputs.error_text);
if (bindto == NULL) {
efree(host);
return -1;
}
}

#ifdef SO_BROADCAST
Expand Down