core: stop redefining E* macros on Windows, map EACCES, related fixes

Before this patch, standard `E*` errno codes were redefined on Windows,
onto matching winsock2 `WSA*` error codes, which have different values.
This broke uses where using the `E*` value in non-socket context, or
other places expecting a POSIX `errno`, e.g. file I/O, threads, IDN or
interfacing with dependencies.

Fix it by introducing a curl-specific `SOCKE*` set of macros that map to
`WSA*` on Windows and standard POSIX codes on other platforms. Then
verify and update the code to use `SOCKE*` or `E*` macro depending on
context.

- Add `SOCKE*` macros that map to either winsock2 or POSIX error codes.
  And use them with `SOCKERRNO` or in contexts requiring
  platform-dependent socket error codes.

  This fixes `E*` uses which were supposed be POSIX values, not `WSA*`
  socket errors, on Windows:
  - lib/curl_multibyte.c
  - lib/curl_threads.c
  - lib/idn.c
  - lib/vtls/gtls.c
  - lib/vtls/rustls.c
  - src/tool_cb_wrt.c
  - src/tool_dirhie.c

- Ban `E*` codes having a `SOCKE*` mapping, via checksrc.
  Authored-by: Daniel Stenberg

- Add exceptions for `E*` codes used in file I/O, or other contexts
  requiring POSIX error codes.

Also:
- ftp: fix missing `SOCKEACCES` mapping for Windows.
- add `SOCKENOMEM` for `Curl_getaddrinfo()` via `asyn-thread.c`.
- tests/server/sockfilt: fix to set `SOCKERRNO` in local `select()`
  override on Windows.
- lib/inet_ntop: fix to return `WSAEINVAL` on Windows, where `ENOSPC` is
  used on other platforms. To simulate Windows' built-in `inet_ntop()`,
  as tested on a Win10 machine.
  Note:
  - WINE returns `STATUS_INVALID_PARAMETER` = `0xC000000D`.
  - Microsoft documentation says it returns `WSA_INVALID_PARAMETER`
    (= `ERROR_INVALID_PARAMETER`) 87:
    https://learn.microsoft.com/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_ntop#return-value
- lib/inet_ntop: drop redundant `CURL_SETERRNO(ENOSPC)`.
  `inet_ntop4()` already sets it before returning `NULL`.
- replace stray `WSAEWOULDBLOCK` with `USE_WINSOCK` macro to detect
  winsock2.
- move existing `SOCKE*` mappings from `tests/server` to
  `curl_setup_once.h`.
- add missing `EINTR`, `EINVAL` constants for WinCE.

Follow-up to abf80aae38 #16612
Follow-up to d69425ed7d #16615
Bug: https://github.com/curl/curl/pull/16553#issuecomment-2704679377

Closes #16621
This commit is contained in:
Viktor Szakats 2025-03-08 02:18:35 +01:00
parent c0a70c564d
commit 51d8213579
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
36 changed files with 152 additions and 114 deletions

View file

@ -228,6 +228,7 @@ static ssize_t fullread(int filedes, void *buffer, size_t nbytes)
if(rc < 0) {
error = errno;
/* !checksrc! disable ERRNOVAR 1 */
if((error == EINTR) || (error == EAGAIN))
continue;
if(error == CURL_WIN32_EPIPE) {
@ -279,6 +280,7 @@ static ssize_t fullwrite(int filedes, const void *buffer, size_t nbytes)
if(wc < 0) {
error = errno;
/* !checksrc! disable ERRNOVAR 1 */
if((error == EINTR) || (error == EAGAIN))
continue;
logmsg("writing to file descriptor: %d,", filedes);
@ -624,7 +626,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
/* check if the input value is valid */
if(nfds < 0) {
CURL_SETERRNO(EINVAL);
SET_SOCKERRNO(SOCKEINVAL);
return -1;
}
@ -645,7 +647,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
/* create internal event to abort waiting threads */
abort = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!abort) {
CURL_SETERRNO(ENOMEM);
SET_SOCKERRNO(SOCKENOMEM);
return -1;
}
@ -653,7 +655,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
data = calloc(nfds, sizeof(struct select_ws_data));
if(!data) {
CloseHandle(abort);
CURL_SETERRNO(ENOMEM);
SET_SOCKERRNO(SOCKENOMEM);
return -1;
}
@ -662,7 +664,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
if(!handles) {
CloseHandle(abort);
free(data);
CURL_SETERRNO(ENOMEM);
SET_SOCKERRNO(SOCKENOMEM);
return -1;
}