curlx/strerr: use strerror_s() on Windows

To replace deprecated, unsafe `sys_nerr`, `sys_errlist` global
variables with the function suggested by the CRT warning silenced via
`_CRT_SECURE_NO_WARNINGS`:
```
lib/curlx/strerr.c(291): warning C4996: '__sys_nerr': This function or variable may be unsafe. Consider using strerror instead.
lib/curlx/strerr.c(292): warning C4996: '__sys_errlist': This function or variable may be unsafe. Consider using strerror instead.
```
(where `strerror` in turn suggests `strerror_s`...)

Upside: returns an error and has a Unicode variant. Downaside: happy
to return success when passing unrecognized error codes. Work it around
by looking for the string "Unknown error" returned in such cases and
falling back to other methods to retrieve a description.

Refs:
https://learn.microsoft.com/cpp/c-runtime-library/errno-doserrno-sys-errlist-and-sys-nerr
https://learn.microsoft.com/cpp/c-runtime-library/reference/strerror-s-strerror-s-wcserror-s-wcserror-s

Closes #19646
This commit is contained in:
Viktor Szakats 2025-11-21 15:55:33 +01:00
parent 82013066a6
commit 1eca08a541
No known key found for this signature in database
GPG Key ID: B5ABD165E2AEF201
2 changed files with 7 additions and 12 deletions

View File

@ -95,9 +95,9 @@
unlink(), etc. */
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS /* for __sys_errlist, __sys_nerr, _open(),
_wfopen(), _wopen(), fopen(), freopen(),
getenv(), gmtime(), sprintf(), strcpy(),
#define _CRT_SECURE_NO_WARNINGS /* for _open(), _wfopen(), _wopen(), fopen(),
freopen(), getenv(), gmtime(), sprintf(),
strcpy(),
in tests: localtime(), open(), sscanf() */
#endif
#endif /* _MSC_VER */

View File

@ -287,17 +287,12 @@ const char *curlx_strerror(int err, char *buf, size_t buflen)
*buf = '\0';
#ifdef _WIN32
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
SNPRINTF(buf, buflen, "%s", sys_errlist[err]);
else {
if(
if((!strerror_s(buf, buflen, err) || !strcmp(buf, "Unknown error")) &&
#ifdef USE_WINSOCK
!get_winsock_error(err, buf, buflen) &&
!get_winsock_error(err, buf, buflen) &&
#endif
!curlx_get_winapi_error((DWORD)err, buf, buflen))
SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err);
}
!curlx_get_winapi_error((DWORD)err, buf, buflen))
SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err);
#else /* !_WIN32 */
#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)