Module: wine Branch: refs/heads/master Commit: dcbfa1179d32a5762388ee079dec546d5feeeced URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=dcbfa1179d32a5762388ee07...
Author: Detlef Riekenberg wine.dev@web.de Date: Sun Mar 19 19:35:36 2006 +0100
kernel: Avoid heap corruption on invalid parameter in GlobalFree().
---
dlls/kernel/heap.c | 23 ++++++++++++++++++----- dlls/kernel/tests/heap.c | 23 ++++++++++++++++++++++- 2 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel/heap.c b/dlls/kernel/heap.c index 59a5e9f..a5849ed 100644 --- a/dlls/kernel/heap.c +++ b/dlls/kernel/heap.c @@ -683,13 +683,19 @@ HGLOBAL WINAPI GlobalReAlloc( * * Free a global memory object. * + * PARAMS + * hmem [I] Handle of the global memory object + * * RETURNS - * NULL: Success - * Handle: Failure + * Success: NULL + * Failure: The provided handle + * + * NOTES + * When the handle is invalid, last error is set to ERROR_INVALID_HANDLE + * */ -HGLOBAL WINAPI GlobalFree( - HGLOBAL hmem /* [in] Handle of global memory object */ -) { +HGLOBAL WINAPI GlobalFree(HGLOBAL hmem) +{ PGLOBAL32_INTERN pintern; HGLOBAL hreturned;
@@ -707,6 +713,7 @@ HGLOBAL WINAPI GlobalFree(
if(pintern->Magic==MAGIC_GLOBAL_USED) { + pintern->Magic = 0xdead;
/* WIN98 does not make this test. That is you can free a */ /* block you have not unlocked. Go figure!! */ @@ -719,6 +726,12 @@ HGLOBAL WINAPI GlobalFree( if(!HeapFree(GetProcessHeap(), 0, pintern)) hreturned=hmem; } + else + { + WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic); + SetLastError(ERROR_INVALID_HANDLE); + hreturned = hmem; + } } } __EXCEPT_PAGE_FAULT diff --git a/dlls/kernel/tests/heap.c b/dlls/kernel/tests/heap.c index a6284a0..e1a535c 100644 --- a/dlls/kernel/tests/heap.c +++ b/dlls/kernel/tests/heap.c @@ -25,6 +25,8 @@ #include "winbase.h" #include "wine/test.h"
+#define MAGIC_DEAD 0xdeadbeef + static SIZE_T resize_9x(SIZE_T size) { DWORD dwSizeAligned = (size + 3) & ~3; @@ -35,7 +37,8 @@ START_TEST(heap) { void *mem; HGLOBAL gbl; - SIZE_T size; + HGLOBAL hsecond; + SIZE_T size;
/* Heap*() functions */ mem = HeapAlloc(GetProcessHeap(), 0, 0); @@ -75,6 +78,15 @@ START_TEST(heap) gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE); ok(gbl == NULL, "global realloc allocated memory\n");
+ /* invalid handles are catched in windows */ + gbl = GlobalAlloc(GMEM_MOVEABLE, 256); + GlobalFree(gbl); + SetLastError(MAGIC_DEAD); + hsecond = GlobalFree(gbl); /* invalid handle: free memory twice */ + ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE), + "returned %p with 0x%08lx (expected %p with ERROR_INVALID_HANDLE)\n", + hsecond, GetLastError(), gbl); + /* Local*() functions */ gbl = LocalAlloc(LMEM_MOVEABLE, 0); ok(gbl != NULL, "local memory not allocated for size 0\n"); @@ -96,6 +108,15 @@ START_TEST(heap) gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE); ok(gbl == NULL, "local realloc allocated memory\n");
+ /* invalid handles are catched in windows */ + gbl = LocalAlloc(GMEM_MOVEABLE, 256); + LocalFree(gbl); + SetLastError(MAGIC_DEAD); + hsecond = LocalFree(gbl); /* invalid handle: free memory twice */ + ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE), + "returned %p with 0x%08lx (expected %p with ERROR_INVALID_HANDLE)\n", + hsecond, GetLastError(), gbl); + /* trying to lock empty memory should give an error */ gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0); ok(gbl != NULL, "returned NULL\n");