Skip to content

Commit edcd6cc

Browse files
authored
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.
1 parent 50b3a0d commit edcd6cc

File tree

2 files changed

+15
-12
lines changed

2 files changed

+15
-12
lines changed

main/network.c

+14-7
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,7 @@ const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
8888
#endif
8989

9090
#ifdef HAVE_GETADDRINFO
91-
#ifdef HAVE_GAI_STRERROR
92-
# define PHP_GAI_STRERROR(x) (gai_strerror(x))
93-
#else
94-
# define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
91+
# if !defined(PHP_WIN32) && !defined(HAVE_GAI_STRERROR)
9592
/* {{{ php_gai_strerror */
9693
static const char *php_gai_strerror(int code)
9794
{
@@ -129,7 +126,7 @@ static const char *php_gai_strerror(int code)
129126
return "Unknown error";
130127
}
131128
/* }}} */
132-
#endif
129+
# endif
133130
#endif
134131

135132
/* {{{ php_network_freeaddresses */
@@ -193,16 +190,26 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
193190
# endif
194191

195192
if ((n = getaddrinfo(host, NULL, &hints, &res))) {
193+
# if defined(PHP_WIN32)
194+
char *gai_error = php_win32_error_to_msg(n);
195+
# elif defined(HAVE_GAI_STRERROR)
196+
const char *gai_error = gai_strerror(n);
197+
# else
198+
const char *gai_error = php_gai_strerror(n)
199+
# endif
196200
if (error_string) {
197201
/* free error string received during previous iteration (if any) */
198202
if (*error_string) {
199203
zend_string_release_ex(*error_string, 0);
200204
}
201-
*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, PHP_GAI_STRERROR(n));
205+
*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
202206
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
203207
} else {
204-
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, PHP_GAI_STRERROR(n));
208+
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
205209
}
210+
# if PHP_WIN32
211+
php_win32_error_msg_free(gai_error);
212+
# endif
206213
return 0;
207214
} else if (res == NULL) {
208215
if (error_string) {

win32/build/config.w32

+1-5
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,9 @@ STDOUT.WriteBlankLines(1);
324324
/* Can we build with IPv6 support? */
325325
ARG_ENABLE("ipv6", "Disable IPv6 support (default is turn it on if available)", "yes");
326326

327-
var main_network_has_ipv6 = 0;
327+
AC_DEFINE('HAVE_GAI_STRERROR', 1);
328328
if (PHP_IPV6 == "yes") {
329-
main_network_has_ipv6 = CHECK_HEADER_ADD_INCLUDE("wspiapi.h", "CFLAGS") ? 1 : 0;
330-
}
331-
if (main_network_has_ipv6) {
332329
STDOUT.WriteLine("Enabling IPv6 support");
333-
AC_DEFINE('HAVE_GAI_STRERROR', 1);
334330
AC_DEFINE('HAVE_IPV6', 1);
335331
}
336332

0 commit comments

Comments
 (0)