]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
windows: determine `RtlVerifyVersionInfo` address on global init
authorViktor Szakats <commit@vsz.me>
Sun, 8 Mar 2026 14:12:17 +0000 (15:12 +0100)
committerViktor Szakats <commit@vsz.me>
Mon, 9 Mar 2026 10:35:19 +0000 (11:35 +0100)
Instead of the first internal call to `curlx_verify_windows_version()`.

To avoid the chance of a race, potentially resulting in initializing
this address twice. AFAICT it could not cause an issue before this
patch.

Reported by Codex Security

Follow-up to b17ef873ae2151263667f4b6fb6abfe337e687dc #18009

Closes #20853

lib/curlx/version_win32.c
lib/curlx/version_win32.h
lib/system_win32.c
src/tool_doswin.c

index 1229c393173b6150c60f9e44a8bc9af9ec6e3408..296a38d9247b176476cd5613ca6c7d1859bd1875 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "curlx/version_win32.h"
 
+#ifndef CURL_WINDOWS_UWP
 /* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW)
    and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */
 struct OUR_OSVERSIONINFOEXW {
@@ -43,6 +44,24 @@ struct OUR_OSVERSIONINFOEXW {
   UCHAR  wReserved;
 };
 
+typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
+  (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
+static RTLVERIFYVERSIONINFO_FN s_pRtlVerifyVersionInfo;
+
+void curlx_verify_windows_init(void)
+{
+#if defined(__clang__) && __clang_major__ >= 16
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-function-type-strict"
+#endif
+  s_pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN,
+    GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlVerifyVersionInfo"));
+#if defined(__clang__) && __clang_major__ >= 16
+#pragma clang diagnostic pop
+#endif
+}
+#endif /* !CURL_WINDOWS_UWP */
+
 /*
  * curlx_verify_windows_version()
  *
@@ -115,24 +134,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
   DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION |
                      VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
 
-  typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
-    (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
-  static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo;
-  static bool onetime = TRUE; /* safe because first call is during init */
-
-  if(onetime) {
-#if defined(__clang__) && __clang_major__ >= 16
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-function-type-strict"
-#endif
-    pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN,
-      GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlVerifyVersionInfo"));
-#if defined(__clang__) && __clang_major__ >= 16
-#pragma clang diagnostic pop
-#endif
-    onetime = FALSE;
-  }
-
   switch(condition) {
   case VERSION_LESS_THAN:
     majorCondition = VER_LESS;
@@ -203,8 +204,8 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
      the real version always, so we use the Rtl variant of the function when
      possible. Note though the function signatures have underlying fundamental
      types that are the same, the return values are different. */
-  if(pRtlVerifyVersionInfo)
-    matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+  if(s_pRtlVerifyVersionInfo)
+    matched = !s_pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
   else
     matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, dwTypeMask, cm);
 
@@ -222,8 +223,8 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
 
     cm = VerSetConditionMask(0, VER_BUILDNUMBER, buildCondition);
     dwTypeMask = VER_BUILDNUMBER;
-    if(pRtlVerifyVersionInfo)
-      matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+    if(s_pRtlVerifyVersionInfo)
+      matched = !s_pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
     else
       matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
                                      dwTypeMask, cm);
index 569626afc8d8db6eab8b2cf479f8d11379fcda5b..c4a1c0f7586b7aca8c0e82abab2378af96c92706 100644 (file)
@@ -43,6 +43,11 @@ typedef enum {
   PLATFORM_WINNT
 } PlatformIdentifier;
 
+#ifdef CURL_WINDOWS_UWP
+#define curlx_verify_windows_init() Curl_nop_stmt
+#else
+void curlx_verify_windows_init(void);
+#endif
 /* This is used to verify if we are running on a specific Windows version */
 bool curlx_verify_windows_version(const unsigned int majorVersion,
                                   const unsigned int minorVersion,
index f91a81a113f2647a8af2543bed9335720c53720a..1b052357b5dd4f7b41117bae8e6e2df05d9603f6 100644 (file)
@@ -28,6 +28,7 @@
 #include "system_win32.h"
 #include "curl_sspi.h"
 #include "curlx/timeval.h"
+#include "curlx/version_win32.h"  /* for curlx_verify_windows_init() */
 
 /* Curl_win32_init() performs Win32 global initialization */
 CURLcode Curl_win32_init(long flags)
@@ -77,6 +78,7 @@ CURLcode Curl_win32_init(long flags)
   }
 #endif
 
+  curlx_verify_windows_init();
   curlx_now_init();
   return CURLE_OK;
 }
index c56a41d081854d1992a9b7966d4419bbc005b3c5..ad0386555dbd8c4778c82ef14ea5f8167f831420 100644 (file)
@@ -901,6 +901,7 @@ curl_socket_t win32_stdin_read_thread(void)
 
 CURLcode win32_init(void)
 {
+  curlx_verify_windows_init();
   curlx_now_init();
 #ifndef CURL_WINDOWS_UWP
   init_terminal();