Module: wine Branch: master Commit: fa359ed9c88b75fd918c5aab5245114a54800dbf URL: https://gitlab.winehq.org/wine/wine/-/commit/fa359ed9c88b75fd918c5aab5245114...
Author: Paul Gofman pgofman@codeweavers.com Date: Thu Aug 4 17:47:32 2022 -0500
winhttp: Avoid invalid memory access in netconn_resolve().
---
dlls/winhttp/net.c | 64 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 13 deletions(-)
diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c index 31d8529f1d7..ab94b5bfd1d 100644 --- a/dlls/winhttp/net.c +++ b/dlls/winhttp/net.c @@ -752,18 +752,51 @@ static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct soc
struct async_resolve { - const WCHAR *hostname; + LONG ref; + WCHAR *hostname; INTERNET_PORT port; - struct sockaddr_storage *addr; + struct sockaddr_storage addr; DWORD result; HANDLE done; };
+static struct async_resolve *create_async_resolve( const WCHAR *hostname, INTERNET_PORT port ) +{ + struct async_resolve *ret; + + if (!(ret = malloc(sizeof(*ret)))) + { + ERR( "No memory.\n" ); + return NULL; + } + ret->ref = 1; + ret->hostname = strdupW( hostname ); + ret->port = port; + if (!(ret->done = CreateEventW( NULL, FALSE, FALSE, NULL ))) + { + free( ret->hostname ); + free( ret ); + return NULL; + } + return ret; +} + +static void async_resolve_release( struct async_resolve *async ) +{ + if (InterlockedDecrement( &async->ref )) return; + + free( async->hostname ); + CloseHandle( async->done ); + free( async ); +} + static void CALLBACK resolve_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) { struct async_resolve *async = ctx; - async->result = resolve_hostname( async->hostname, async->port, async->addr ); + + async->result = resolve_hostname( async->hostname, async->port, &async->addr ); SetEvent( async->done ); + async_resolve_release( async ); }
DWORD netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr, int timeout ) @@ -773,20 +806,25 @@ DWORD netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_stor if (!timeout) ret = resolve_hostname( hostname, port, addr ); else { - struct async_resolve async; + struct async_resolve *async; + + if (!(async = create_async_resolve( hostname, port ))) + return ERROR_OUTOFMEMORY;
- async.hostname = hostname; - async.port = port; - async.addr = addr; - if (!(async.done = CreateEventW( NULL, FALSE, FALSE, NULL ))) return GetLastError(); - if (!TrySubmitThreadpoolCallback( resolve_proc, &async, NULL )) + InterlockedIncrement( &async->ref ); + if (!TrySubmitThreadpoolCallback( resolve_proc, async, NULL )) { - CloseHandle( async.done ); + InterlockedDecrement( &async->ref ); + async_resolve_release( async ); return GetLastError(); } - if (WaitForSingleObject( async.done, timeout ) != WAIT_OBJECT_0) ret = ERROR_WINHTTP_TIMEOUT; - else ret = async.result; - CloseHandle( async.done ); + if (WaitForSingleObject( async->done, timeout ) != WAIT_OBJECT_0) ret = ERROR_WINHTTP_TIMEOUT; + else + { + *addr = async->addr; + ret = async->result; + } + async_resolve_release( async ); }
return ret;