Hans Leidekker : webservices: Protect heaps with a critical section.

Alexandre Julliard julliard at winehq.org
Wed Mar 8 16:01:38 CST 2017


Module: wine
Branch: master
Commit: dea8708079414d26c4ab41d539da9cc7451a5d4c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dea8708079414d26c4ab41d539da9cc7451a5d4c

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Mar  8 11:25:59 2017 +0100

webservices: Protect heaps with a critical section.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c | 182 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 134 insertions(+), 48 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 8c538ea..6c95d8a 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -284,13 +284,17 @@ static const struct prop_desc heap_props[] =
 
 struct heap
 {
-    HANDLE      handle;
-    SIZE_T      max_size;
-    SIZE_T      allocated;
-    ULONG       prop_count;
-    struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])];
+    ULONG            magic;
+    CRITICAL_SECTION cs;
+    HANDLE           handle;
+    SIZE_T           max_size;
+    SIZE_T           allocated;
+    ULONG            prop_count;
+    struct prop      prop[sizeof(heap_props)/sizeof(heap_props[0])];
 };
 
+#define HEAP_MAGIC (('H' << 24) | ('E' << 16) | ('A' << 8) | 'P')
+
 static BOOL ensure_heap( struct heap *heap )
 {
     SIZE_T size;
@@ -304,31 +308,48 @@ static BOOL ensure_heap( struct heap *heap )
 
 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
 {
-    void *ret;
     struct heap *heap = (struct heap *)handle;
-    if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) return NULL;
+    void *ret = NULL;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC) goto done;
+    if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) goto done;
     if ((ret = HeapAlloc( heap->handle, 0, size ))) heap->allocated += size;
+
+done:
+    LeaveCriticalSection( &heap->cs );
     return ret;
 }
 
 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
 {
-    void *ret;
     struct heap *heap = (struct heap *)handle;
-    if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) return NULL;
+    void *ret = NULL;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC) goto done;
+    if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) goto done;
     if ((ret = HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size ))) heap->allocated += size;
+
+done:
+    LeaveCriticalSection( &heap->cs );
     return ret;
 }
 
 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_T new_size )
 {
-    void *ret;
     struct heap *heap = (struct heap *)handle;
-    if (!ensure_heap( heap )) return NULL;
+    void *ret = NULL;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC || !ensure_heap( heap )) goto done;
     if (new_size >= old_size)
     {
         SIZE_T size = new_size - old_size;
-        if (size > heap->max_size - heap->allocated) return NULL;
+        if (size > heap->max_size - heap->allocated) goto done;
         if ((ret = HeapReAlloc( heap->handle, 0, ptr, new_size ))) heap->allocated += size;
     }
     else
@@ -336,18 +357,24 @@ void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_T new_size )
         SIZE_T size = old_size - new_size;
         if ((ret = HeapReAlloc( heap->handle, 0, ptr, new_size ))) heap->allocated -= size;
     }
+
+done:
+    LeaveCriticalSection( &heap->cs );
     return ret;
 }
 
 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_T new_size )
 {
-    void *ret;
     struct heap *heap = (struct heap *)handle;
-    if (!ensure_heap( heap )) return NULL;
+    void *ret = NULL;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC || !ensure_heap( heap )) goto done;
     if (new_size >= old_size)
     {
         SIZE_T size = new_size - old_size;
-        if (size > heap->max_size - heap->allocated) return NULL;
+        if (size > heap->max_size - heap->allocated) goto done;
         if ((ret = HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, new_size ))) heap->allocated += size;
     }
     else
@@ -355,15 +382,25 @@ static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_
         SIZE_T size = old_size - new_size;
         if ((ret = HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, new_size ))) heap->allocated -= size;
     }
+
+done:
+    LeaveCriticalSection( &heap->cs );
     return ret;
 }
 
 void ws_free( WS_HEAP *handle, void *ptr, SIZE_T size )
 {
     struct heap *heap = (struct heap *)handle;
-    if (!heap->handle) return;
-    HeapFree( heap->handle, 0, ptr );
-    heap->allocated -= size;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic == HEAP_MAGIC)
+    {
+        HeapFree( heap->handle, 0, ptr );
+        heap->allocated -= size;
+    }
+
+    LeaveCriticalSection( &heap->cs );
 }
 
 /**************************************************************************
@@ -389,6 +426,11 @@ static struct heap *alloc_heap(void)
     ULONG size = sizeof(*ret) + prop_size( heap_props, count );
 
     if (!(ret = heap_alloc_zero( size ))) return NULL;
+
+    ret->magic      = HEAP_MAGIC;
+    InitializeCriticalSection( &ret->cs );
+    ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": heap.cs");
+
     prop_init( heap_props, count, ret->prop, &ret[1] );
     ret->prop_count = count;
     return ret;
@@ -415,6 +457,13 @@ HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PR
     return S_OK;
 }
 
+static void reset_heap( struct heap *heap )
+{
+    HeapDestroy( heap->handle );
+    heap->handle   = NULL;
+    heap->max_size = heap->allocated = 0;
+}
+
 /**************************************************************************
  *          WsFreeHeap		[webservices.@]
  */
@@ -425,7 +474,22 @@ void WINAPI WsFreeHeap( WS_HEAP *handle )
     TRACE( "%p\n", handle );
 
     if (!heap) return;
-    HeapDestroy( heap->handle );
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC)
+    {
+        LeaveCriticalSection( &heap->cs );
+        return;
+    }
+
+    reset_heap( heap );
+    heap->magic = 0;
+
+    LeaveCriticalSection( &heap->cs );
+
+    heap->cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection( &heap->cs );
     heap_free( heap );
 }
 
@@ -441,12 +505,60 @@ HRESULT WINAPI WsResetHeap( WS_HEAP *handle, WS_ERROR *error )
 
     if (!heap) return E_INVALIDARG;
 
-    HeapDestroy( heap->handle );
-    heap->handle   = NULL;
-    heap->max_size = heap->allocated = 0;
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC)
+    {
+        LeaveCriticalSection( &heap->cs );
+        return E_INVALIDARG;
+    }
+
+    reset_heap( heap );
+
+    LeaveCriticalSection( &heap->cs );
     return S_OK;
 }
 
+/**************************************************************************
+ *          WsGetHeapProperty		[webservices.@]
+ */
+HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
+                                  ULONG size, WS_ERROR *error )
+{
+    struct heap *heap = (struct heap *)handle;
+    HRESULT hr = S_OK;
+
+    TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
+    if (error) FIXME( "ignoring error parameter\n" );
+
+    if (!heap) return E_INVALIDARG;
+
+    EnterCriticalSection( &heap->cs );
+
+    if (heap->magic != HEAP_MAGIC)
+    {
+        LeaveCriticalSection( &heap->cs );
+        return E_INVALIDARG;
+    }
+
+    switch (id)
+    {
+    case WS_HEAP_PROPERTY_REQUESTED_SIZE:
+    case WS_HEAP_PROPERTY_ACTUAL_SIZE:
+    {
+        SIZE_T *heap_size = buf;
+        if (!buf || size != sizeof(heap_size)) hr = E_INVALIDARG;
+        else *heap_size = heap->allocated;
+        break;
+    }
+    default:
+        hr = prop_get( heap->prop, heap->prop_count, id, buf, size );
+    }
+
+    LeaveCriticalSection( &heap->cs );
+    return hr;
+}
+
 struct node *alloc_node( WS_XML_NODE_TYPE type )
 {
     struct node *ret;
@@ -961,32 +1073,6 @@ HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASY
 }
 
 /**************************************************************************
- *          WsGetHeapProperty		[webservices.@]
- */
-HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
-                                  ULONG size, WS_ERROR *error )
-{
-    struct heap *heap = (struct heap *)handle;
-
-    TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
-    if (error) FIXME( "ignoring error parameter\n" );
-
-    switch (id)
-    {
-    case WS_HEAP_PROPERTY_REQUESTED_SIZE:
-    case WS_HEAP_PROPERTY_ACTUAL_SIZE:
-    {
-        SIZE_T *heap_size = buf;
-        if (!buf || size != sizeof(heap_size)) return E_INVALIDARG;
-        *heap_size = heap->allocated;
-        return S_OK;
-    }
-    default:
-        return prop_get( heap->prop, heap->prop_count, id, buf, size );
-    }
-}
-
-/**************************************************************************
  *          WsGetNamespaceFromPrefix		[webservices.@]
  */
 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,




More information about the wine-cvs mailing list