Paul Gofman : winhttp: Avoid invalid memory access in netconn_resolve().
Alexandre Julliard
julliard at winehq.org
Fri Aug 5 14:42:32 CDT 2022
Module: wine
Branch: master
Commit: fa359ed9c88b75fd918c5aab5245114a54800dbf
URL: https://gitlab.winehq.org/wine/wine/-/commit/fa359ed9c88b75fd918c5aab5245114a54800dbf
Author: Paul Gofman <pgofman at 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;
More information about the wine-cvs
mailing list