-
Notifications
You must be signed in to change notification settings - Fork 7.9k
gai_strerror() is not thread-safe on Windows #15568
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
Conversation
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.
FWIW, I brought up in GH-15555 about using |
Making IPv6 mandatory seems like a good idea, and would render this patch moot (if we require IPv6 for PHP 8.4, what might be a bit late), but the main point of this PR is to avoid calling |
Yeah, it's probably too late to get any v6 changes in for 8.4, but refactors that get us further there are still a good idea. |
We extract `report_getaddrinfo_failure()`, and refactor that further. While this code is now a tad bit slower, that shouldn't matter since it is error handling. We also cheat a bit, since adding a proper format specifier for `php_error_docref()` is not a proper refactoring, but more like a bug fix.
main/network.c
Outdated
} else { | ||
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, PHP_GAI_STRERROR(n)); | ||
} | ||
report_getaddrinfo_failure(host, n, error_string); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code in the } else if (res == NULL) {
below could also call report_getaddrinfo_failure()
, but the two legs have slightly different error messages: one shows errno
, but not the other. I doubt that showing errno
here is correct (since getaddrinfo()
has apparently not failed, but I'm not sure. I'm not even sure if that code would ever be executed; isn't res
supposed to be set if getaddrinfo()
returns 0
?
This reverts commit 7b151af2103216295ed82e87d38dae3663ddc35a.
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.
This PR is mainly about avoiding
gai_strerror()
on Windows, because the function is not thread-safe there[1].However, it also fixes the IPv6 configuration on Windows where
HAVE_GAI_STRERROR
only was defined if IPv6 support is requested (the default; can be disabled with--disable-ipv6
), although that function is generally available. For BC, we defineHAVE_GAI_STRERROR
but do no longer use it internally. If extensions use it, they should be fixed (if necessary), but we don't want to break them that late in the pre-release cycle of PHP 8.4.Note that I'm fine with dropping the changes to config.w32, but the 5th commit should be merged (maybe in a different form; code is not nice as is).
[1] https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-gai_strerrora
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 came up in #15567, and solves the easy part. Not using
gai_strerror()
on Windows, because it is not thread-safe would be as simple asdefine PHP_GAI_STRERROR(x) (php_win32_error_to_msg(x))
if there wasn't a memory leak because the returned buffer needs to be freed by the caller. Any suggestions on how to solve this in a clean way are welcome!