easy: fix win32 init to work without CURL_GLOBAL_WIN32

- Change the behavior of win32_init so that the required initialization
  procedures are not affected by CURL_GLOBAL_WIN32 flag.

libcurl via curl_global_init supports initializing for win32 with an
optional flag CURL_GLOBAL_WIN32, which if omitted was meant to stop
Winsock initialization. It did so internally by skipping win32_init()
when that flag was set. Since then win32_init() has been expanded to
include required initialization routines that are separate from
Winsock and therefore must be called in all cases. This commit fixes
it so that CURL_GLOBAL_WIN32 only controls the optional win32
initialization (which is Winsock initialization, according to our doc).

The only users affected by this change are those that don't pass
CURL_GLOBAL_WIN32 to curl_global_init. For them this commit removes the
risk of a potential crash.

Ref: https://github.com/curl/curl/pull/3573

Fixes https://github.com/curl/curl/issues/3313
Closes https://github.com/curl/curl/pull/3575
This commit is contained in:
Jay Satiro 2019-02-16 18:55:40 -05:00
parent e6522522f9
commit f26bc29cfe
1 changed files with 60 additions and 49 deletions

View File

@ -84,63 +84,76 @@
void Curl_version_init(void); void Curl_version_init(void);
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite /* true globals -- for curl_global_init() and curl_global_cleanup() */
of win32_init() */ static unsigned int initialized;
static void win32_cleanup(void) static long init_flags;
/*
* win32 init and cleanup functions
*/
#ifdef WIN32
/* win32_cleanup() is the opposite of win32_init() */
static void win32_cleanup()
{ {
#ifdef USE_WINSOCK
WSACleanup();
#endif
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
Curl_sspi_global_cleanup(); Curl_sspi_global_cleanup();
#endif #endif
if(init_flags & CURL_GLOBAL_WIN32) {
#ifdef USE_WINSOCK
WSACleanup();
#endif
}
} }
#ifdef WIN32
LARGE_INTEGER Curl_freq; LARGE_INTEGER Curl_freq;
bool Curl_isVistaOrGreater; bool Curl_isVistaOrGreater;
#endif
/* win32_init() performs win32 socket initialization to properly setup the /* win32_init() performs win32 global initialization */
stack to allow networking */ static CURLcode win32_init(long flags)
static CURLcode win32_init(void)
{ {
/* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
is just for Winsock at the moment. Any required win32 initialization
should take place after this block. */
if(flags & CURL_GLOBAL_WIN32) {
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WORD wVersionRequested; WORD wVersionRequested;
WSADATA wsaData; WSADATA wsaData;
int res; int res;
#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
Error IPV6_requires_winsock2 #error IPV6_requires_winsock2
#endif #endif
wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
res = WSAStartup(wVersionRequested, &wsaData); res = WSAStartup(wVersionRequested, &wsaData);
if(res != 0) if(res != 0)
/* Tell the user that we couldn't find a usable */ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */ /* winsock.dll. */
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports what we need.*/ /* Confirm that the Windows Sockets DLL supports what we need.*/
/* Note that if the DLL supports versions greater */ /* Note that if the DLL supports versions greater */
/* than wVersionRequested, it will still return */ /* than wVersionRequested, it will still return */
/* wVersionRequested in wVersion. wHighVersion contains the */ /* wVersionRequested in wVersion. wHighVersion contains the */
/* highest supported version. */ /* highest supported version. */
if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
/* Tell the user that we couldn't find a usable */ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */ /* winsock.dll. */
WSACleanup(); WSACleanup();
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
/* The Windows Sockets DLL is acceptable. Proceed. */ /* The Windows Sockets DLL is acceptable. Proceed. */
#elif defined(USE_LWIPSOCK) #elif defined(USE_LWIPSOCK)
lwip_init(); lwip_init();
#endif #endif
} /* CURL_GLOBAL_WIN32 */
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
{ {
@ -150,7 +163,6 @@ static CURLcode win32_init(void)
} }
#endif #endif
#ifdef WIN32
if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) { VERSION_GREATER_THAN_EQUAL)) {
Curl_isVistaOrGreater = TRUE; Curl_isVistaOrGreater = TRUE;
@ -158,14 +170,11 @@ static CURLcode win32_init(void)
} }
else else
Curl_isVistaOrGreater = FALSE; Curl_isVistaOrGreater = FALSE;
#endif
return CURLE_OK; return CURLE_OK;
} }
/* true globals -- for curl_global_init() and curl_global_cleanup() */ #endif /* WIN32 */
static unsigned int initialized;
static long init_flags;
/* /*
* strdup (and other memory functions) is redefined in complicated * strdup (and other memory functions) is redefined in complicated
@ -239,11 +248,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if(flags & CURL_GLOBAL_WIN32) #ifdef WIN32
if(win32_init()) { if(win32_init(flags)) {
DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
#endif
#ifdef __AMIGA__ #ifdef __AMIGA__
if(!Curl_amiga_init()) { if(!Curl_amiga_init()) {
@ -347,8 +357,9 @@ void curl_global_cleanup(void)
Curl_ssl_cleanup(); Curl_ssl_cleanup();
Curl_resolver_global_cleanup(); Curl_resolver_global_cleanup();
if(init_flags & CURL_GLOBAL_WIN32) #ifdef WIN32
win32_cleanup(); win32_cleanup();
#endif
Curl_amiga_cleanup(); Curl_amiga_cleanup();