curlx: replace mbstowcs/wcstombs with _s counterparts (Windows)

They are used in Windows-specific `fopen()`, `freopen`, `open()` and
`curlx_get_winapi_error()` calls, and in `fix_excessive_path()` in
Unicode builds.

Refs:
https://learn.microsoft.com/cpp/c-runtime-library/reference/mbstowcs-mbstowcs-l
https://learn.microsoft.com/cpp/c-runtime-library/reference/mbstowcs-s-mbstowcs-s-l
https://learn.microsoft.com/cpp/c-runtime-library/reference/wcstombs-wcstombs-l
https://learn.microsoft.com/cpp/c-runtime-library/reference/wcstombs-s-wcstombs-s-l

Also ban these functions via checksrc.

Co-authored-by: Jay Satiro

Closes #19581
This commit is contained in:
Viktor Szakats 2025-11-18 01:48:04 +01:00
parent acfcc2b288
commit 18b9429313
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
4 changed files with 28 additions and 29 deletions

View file

@ -97,8 +97,7 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS /* for __sys_errlist, __sys_nerr, _open(),
_wfopen(), _wopen(), fopen(), freopen(),
getenv(), gmtime(), mbstowcs(), sprintf(),
strcpy(), wcstombs(),
getenv(), gmtime(), sprintf(), strcpy(),
in tests: localtime(), open(), sscanf() */
#endif
#endif /* _MSC_VER */

View file

@ -97,15 +97,16 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
#ifndef _UNICODE
/* convert multibyte input to unicode */
needed = mbstowcs(NULL, in, 0);
if(needed == (size_t)-1 || needed >= max_path_len)
if(mbstowcs_s(&needed, NULL, 0, in, 0))
goto cleanup;
if(!needed || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
ibuf = (malloc)(needed * sizeof(wchar_t));
if(!ibuf)
goto cleanup;
count = mbstowcs(ibuf, in, needed);
if(count == (size_t)-1 || count >= needed)
if(mbstowcs_s(&count, ibuf, needed, in, needed - 1))
goto cleanup;
if(count != needed)
goto cleanup;
in_w = ibuf;
#else
@ -193,15 +194,16 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
#ifndef _UNICODE
/* convert unicode full path to multibyte output */
needed = wcstombs(NULL, fbuf, 0);
if(needed == (size_t)-1 || needed >= max_path_len)
if(wcstombs_s(&needed, NULL, 0, fbuf, 0))
goto cleanup;
if(!needed || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
obuf = (malloc)(needed);
if(!obuf)
goto cleanup;
count = wcstombs(obuf, fbuf, needed);
if(count == (size_t)-1 || count >= needed)
if(wcstombs_s(&count, obuf, needed, fbuf, needed - 1))
goto cleanup;
if(count != needed)
goto cleanup;
*out = obuf;
obuf = NULL;

View file

@ -52,6 +52,7 @@ const char *curlx_get_winapi_error(DWORD err, char *buf, size_t buflen)
{
char *p;
wchar_t wbuf[256];
DWORD wlen;
if(!buflen)
return NULL;
@ -62,23 +63,18 @@ const char *curlx_get_winapi_error(DWORD err, char *buf, size_t buflen)
/* We return the local codepage version of the error string because if it is
output to the user's terminal it will likely be with functions which
expect the local codepage (eg fprintf, failf, infof). */
if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) {
size_t written = wcstombs(buf, wbuf, buflen - 1);
if(written != (size_t)-1)
buf[written] = '\0';
else
*buf = '\0';
}
/* Truncate multiple lines */
p = strchr(buf, '\n');
if(p) {
if(p > buf && *(p-1) == '\r')
*(p-1) = '\0';
else
*p = '\0';
wlen = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL);
if(wlen && !wcstombs_s(NULL, buf, buflen, wbuf, wlen)) {
/* Truncate multiple lines */
p = strchr(buf, '\n');
if(p) {
if(p > buf && *(p-1) == '\r')
*(p-1) = '\0';
else
*p = '\0';
}
}
return *buf ? buf : NULL;

View file

@ -86,6 +86,8 @@ my %banfunc = (
"wcsdup" => 1,
"wcscpy" => 1,
"wcsncpy" => 1,
"mbstowcs" => 1,
"wcstombs" => 1,
"LoadLibrary" => 1,
"LoadLibraryA" => 1,
"LoadLibraryW" => 1,