curlx/fopen: replace open CRT functions their with `_s` counterparts (Windows)
- `_wopen` -> `_wsopen_s`
- `_open`, `open` -> `_sopen_s`
- `_wfopen` -> `_wfopen_s`
- `fopen` -> `fopen_s`
- `_wfreopen` -> `_wfreopen_s`
- `freopen` -> `freopen_s`
For better error handling and for using the CRT functions recommended
via warnings suppressed by `_CRT_SECURE_NO_WARNINGS`.
Also:
- add missing `freopen_s()` prototype when building with mingw-w64 <5.
https://sourceforge.net/p/mingw-w64/mingw-w64/ci/a5d824654cdc57f6eac1bb581b078986f3eb6856/
- tests/server: replace `open()` in the signal handler with `_sopen_s()`
on Windows.
- tests/server: reduce scope of a checksrc exception to a single line.
- checksrc: ban replaced functions.
Refs:
https://learn.microsoft.com/cpp/c-runtime-library/reference/open-wopen
https://learn.microsoft.com/cpp/c-runtime-library/reference/sopen-s-wsopen-s
https://learn.microsoft.com/cpp/c-runtime-library/reference/freopen-wfreopen
https://learn.microsoft.com/cpp/c-runtime-library/reference/fopen-wfopen
https://learn.microsoft.com/cpp/c-runtime-library/reference/fopen-s-wfopen-s
https://learn.microsoft.com/cpp/c-runtime-library/reference/freopen-s-wfreopen-s
Closes #19643
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 886a881..0e5ebb6 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -95,10 +95,9 @@
unlink(), etc. */
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_WARNINGS /* for _open(), _wfopen(), _wopen(), fopen(),
- freopen(), getenv(), gmtime(), sprintf(),
+#define _CRT_SECURE_NO_WARNINGS /* for getenv(), gmtime(), sprintf(),
strcpy(),
- in tests: localtime(), open(), sscanf() */
+ in tests: localtime(), sscanf() */
#endif
#endif /* _MSC_VER */
diff --git a/lib/curlx/fopen.c b/lib/curlx/fopen.c
index dc1c2bb..0dc9699 100644
--- a/lib/curlx/fopen.c
+++ b/lib/curlx/fopen.c
@@ -51,6 +51,8 @@
#include "multibyte.h"
+#include <share.h> /* for _SH_DENYNO */
+
/* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */
#if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \
(_WIN32_WINNT < _WIN32_WINNT_WIN10)
@@ -244,7 +246,7 @@
target = fixed;
else
target = filename_w;
- result = _wopen(target, oflag, pmode);
+ errno = _wsopen_s(&result, target, oflag, _SH_DENYNO, pmode);
curlx_unicodefree(filename_w);
}
else
@@ -255,7 +257,7 @@
target = fixed;
else
target = filename;
- result = _open(target, oflag, pmode);
+ errno = _sopen_s(&result, target, oflag, _SH_DENYNO, pmode);
#endif
(free)(fixed);
@@ -276,7 +278,7 @@
target = fixed;
else
target = filename_w;
- result = _wfopen(target, mode_w);
+ errno = _wfopen_s(&result, target, mode_w);
}
else
/* !checksrc! disable ERRNOVAR 1 */
@@ -288,14 +290,18 @@
target = fixed;
else
target = filename;
- /* !checksrc! disable BANNEDFUNC 1 */
- result = fopen(target, mode);
+ errno = fopen_s(&result, target, mode);
#endif
(free)(fixed);
return result;
}
+#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR < 5)
+_CRTIMP errno_t __cdecl freopen_s(FILE **file, const char *filename,
+ const char *mode, FILE *stream);
+#endif
+
FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fp)
{
FILE *result = NULL;
@@ -310,7 +316,7 @@
target = fixed;
else
target = filename_w;
- result = _wfreopen(target, mode_w, fp);
+ errno = _wfreopen_s(&result, target, mode_w, fp);
}
else
/* !checksrc! disable ERRNOVAR 1 */
@@ -322,8 +328,7 @@
target = fixed;
else
target = filename;
- /* !checksrc! disable BANNEDFUNC 1 */
- result = freopen(target, mode, fp);
+ errno = freopen_s(&result, target, mode, fp);
#endif
(free)(fixed);
diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl
index a2f458b..d38ffec 100755
--- a/scripts/checksrc.pl
+++ b/scripts/checksrc.pl
@@ -113,6 +113,10 @@
"fopen" => 1,
"freopen" => 1,
"open" => 1,
+ "_open" => 1,
+ "_wfopen" => 1,
+ "_wfreopen" => 1,
+ "_wopen" => 1,
"stat" => 1,
);
diff --git a/tests/server/.checksrc b/tests/server/.checksrc
index 0386c67..163a217 100644
--- a/tests/server/.checksrc
+++ b/tests/server/.checksrc
@@ -6,7 +6,6 @@
allowfunc fprintf
allowfunc freeaddrinfo
allowfunc getaddrinfo
-allowfunc open
allowfunc printf
allowfunc recv
allowfunc send
diff --git a/tests/server/util.c b/tests/server/util.c
index 8d8bf12..ae21ff8 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -27,6 +27,10 @@
#include <fcntl.h>
#endif
+#ifdef _WIN32
+#include <share.h>
+#endif
+
/* This function returns a pointer to STATIC memory. It converts the given
* binary lump to a hex formatted string usable for output in logs or
* whatever.
@@ -359,13 +363,17 @@
(void)!write(STDERR_FILENO, msg, sizeof(msg) - 1);
}
else {
+ int fd = -1;
#ifdef _WIN32
-#define OPENMODE S_IREAD | S_IWRITE
+ if(!_sopen_s(&fd, serverlogfile, O_WRONLY | O_CREAT | O_APPEND,
+ _SH_DENYNO, S_IREAD | S_IWRITE) &&
+ fd != -1) {
#else
-#define OPENMODE S_IRUSR | S_IWUSR
-#endif
- int fd = open(serverlogfile, O_WRONLY | O_CREAT | O_APPEND, OPENMODE);
+ /* !checksrc! disable BANNEDFUNC 1 */
+ fd = open(serverlogfile,
+ O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
if(fd != -1) {
+#endif
static const char msg[] = "exit_signal_handler: called\n";
(void)!write(fd, msg, sizeof(msg) - 1);
close(fd);