gai_strerror() is not thread-safe on Windows (GH-15568)

First we refactor to have only a single usage of `PHP_GAI_STRERROR()`
left; then we drop the macro in favor of calling the different
functions conditionally in an ad-hoc style.

This is necessary because the return value of `php_win32_error_to_msg`
needs to be freed by the caller.

The error messages are no more inline with other error messages, since
`gai_strerror()` apparently always appends a period and a space.

We also properly configure IPv4/v6 on Windows.  Since WSPiApi.h has been
created in 2000, so we can safely assume that it is available everywhere
nowadays.  Furthermore, `gai_strerror()` is available regardless of
whether there is IPv6 support.
This commit is contained in:
Christoph M. Becker 2024-09-08 16:16:40 +02:00 committed by GitHub
parent 50b3a0d011
commit edcd6cc564
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 12 deletions

View File

@ -88,10 +88,7 @@ const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
#endif
#ifdef HAVE_GETADDRINFO
#ifdef HAVE_GAI_STRERROR
# define PHP_GAI_STRERROR(x) (gai_strerror(x))
#else
# define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
# if !defined(PHP_WIN32) && !defined(HAVE_GAI_STRERROR)
/* {{{ php_gai_strerror */
static const char *php_gai_strerror(int code)
{
@ -129,7 +126,7 @@ static const char *php_gai_strerror(int code)
return "Unknown error";
}
/* }}} */
#endif
# endif
#endif
/* {{{ php_network_freeaddresses */
@ -193,16 +190,26 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
# endif
if ((n = getaddrinfo(host, NULL, &hints, &res))) {
# if defined(PHP_WIN32)
char *gai_error = php_win32_error_to_msg(n);
# elif defined(HAVE_GAI_STRERROR)
const char *gai_error = gai_strerror(n);
# else
const char *gai_error = php_gai_strerror(n)
# endif
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 for %s failed: %s", host, PHP_GAI_STRERROR(n));
*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
} else {
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, PHP_GAI_STRERROR(n));
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
}
# if PHP_WIN32
php_win32_error_msg_free(gai_error);
# endif
return 0;
} else if (res == NULL) {
if (error_string) {

View File

@ -324,13 +324,9 @@ STDOUT.WriteBlankLines(1);
/* Can we build with IPv6 support? */
ARG_ENABLE("ipv6", "Disable IPv6 support (default is turn it on if available)", "yes");
var main_network_has_ipv6 = 0;
AC_DEFINE('HAVE_GAI_STRERROR', 1);
if (PHP_IPV6 == "yes") {
main_network_has_ipv6 = CHECK_HEADER_ADD_INCLUDE("wspiapi.h", "CFLAGS") ? 1 : 0;
}
if (main_network_has_ipv6) {
STDOUT.WriteLine("Enabling IPv6 support");
AC_DEFINE('HAVE_GAI_STRERROR', 1);
AC_DEFINE('HAVE_IPV6', 1);
}