`AllocateWithWeakRef` and `AllocateExceptionWithRef` leak the `weakref` allocation if the second allocation throws.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/vccorlib.c | 41 ++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 0071c1a4591..20cc964a16c 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -26,6 +26,7 @@ #include "windows.foundation.h" #include "wine/asm.h" #include "wine/debug.h" +#include "wine/exception.h"
#include "cxx.h" #include "private.h" @@ -85,26 +86,44 @@ HRESULT WINAPI GetIidsFn(unsigned int count, unsigned int *copied, const GUID *s return S_OK; }
+static BOOL try_Allocate(size_t size, void **addr) +{ + if (!(*addr = malloc(size))) + return FALSE; + return TRUE; +} + void *__cdecl Allocate(size_t size) { void *addr;
TRACE("(%Iu)\n", size);
- addr = malloc(size); - if (!addr) + if (!try_Allocate(size, &addr)) __abi_WinRTraiseOutOfMemoryException(); return addr; }
-void *__cdecl AllocateException(size_t size) +static BOOL try_AllocateException(size_t size, void **addr) { struct exception_alloc *base;
+ if (!try_Allocate(offsetof(struct exception_alloc, data[size]), (void **)&base)) + return FALSE; + *addr = &base->data; + return TRUE; +} + +void *__cdecl AllocateException(size_t size) +{ + void *addr; + TRACE("(%Iu)\n", size);
- base = Allocate(offsetof(struct exception_alloc, data[size])); - return &base->data; + if (!try_AllocateException(size, &addr)) + __abi_WinRTraiseOutOfMemoryException(); + + return addr; }
void __cdecl Free(void *addr) @@ -204,7 +223,11 @@ void *__cdecl AllocateWithWeakRef(ptrdiff_t offset, size_t size) if (size > inline_max) { weakref = Allocate(sizeof(*weakref)); - object = Allocate(size); + if (!try_Allocate(size, &object)) + { + Free(weakref); + __abi_WinRTraiseOutOfMemoryException(); + } weakref->is_inline = FALSE; } else /* Perform an inline allocation */ @@ -233,7 +256,11 @@ void *__cdecl AllocateExceptionWithWeakRef(ptrdiff_t offset, size_t size)
/* AllocateExceptionWithWeakRef does not store the control block inline, regardless of size. */ weakref = Allocate(sizeof(*weakref)); - excp = AllocateException(size); + if (!try_AllocateException(size, &excp)) + { + Free(weakref); + __abi_WinRTraiseOutOfMemoryException(); + } *(struct control_block **)((char *)excp + offset) = weakref; weakref->IWeakReference_iface.lpVtbl = &control_block_vtbl; weakref->object = excp;