kernel: Avoid heap corruption on invalid parameter in GlobalFree().

This commit is contained in:
Detlef Riekenberg 2006-03-19 19:35:36 +01:00 committed by Alexandre Julliard
parent 13c2f4742f
commit dcbfa1179d
2 changed files with 40 additions and 6 deletions

View File

@ -683,13 +683,19 @@ HGLOBAL WINAPI GlobalReAlloc(
* *
* Free a global memory object. * Free a global memory object.
* *
* PARAMS
* hmem [I] Handle of the global memory object
*
* RETURNS * RETURNS
* NULL: Success * Success: NULL
* Handle: Failure * Failure: The provided handle
*
* NOTES
* When the handle is invalid, last error is set to ERROR_INVALID_HANDLE
*
*/ */
HGLOBAL WINAPI GlobalFree( HGLOBAL WINAPI GlobalFree(HGLOBAL hmem)
HGLOBAL hmem /* [in] Handle of global memory object */ {
) {
PGLOBAL32_INTERN pintern; PGLOBAL32_INTERN pintern;
HGLOBAL hreturned; HGLOBAL hreturned;
@ -707,6 +713,7 @@ HGLOBAL WINAPI GlobalFree(
if(pintern->Magic==MAGIC_GLOBAL_USED) if(pintern->Magic==MAGIC_GLOBAL_USED)
{ {
pintern->Magic = 0xdead;
/* WIN98 does not make this test. That is you can free a */ /* WIN98 does not make this test. That is you can free a */
/* block you have not unlocked. Go figure!! */ /* block you have not unlocked. Go figure!! */
@ -719,6 +726,12 @@ HGLOBAL WINAPI GlobalFree(
if(!HeapFree(GetProcessHeap(), 0, pintern)) if(!HeapFree(GetProcessHeap(), 0, pintern))
hreturned=hmem; hreturned=hmem;
} }
else
{
WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic);
SetLastError(ERROR_INVALID_HANDLE);
hreturned = hmem;
}
} }
} }
__EXCEPT_PAGE_FAULT __EXCEPT_PAGE_FAULT

View File

@ -25,6 +25,8 @@
#include "winbase.h" #include "winbase.h"
#include "wine/test.h" #include "wine/test.h"
#define MAGIC_DEAD 0xdeadbeef
static SIZE_T resize_9x(SIZE_T size) static SIZE_T resize_9x(SIZE_T size)
{ {
DWORD dwSizeAligned = (size + 3) & ~3; DWORD dwSizeAligned = (size + 3) & ~3;
@ -35,7 +37,8 @@ START_TEST(heap)
{ {
void *mem; void *mem;
HGLOBAL gbl; HGLOBAL gbl;
SIZE_T size; HGLOBAL hsecond;
SIZE_T size;
/* Heap*() functions */ /* Heap*() functions */
mem = HeapAlloc(GetProcessHeap(), 0, 0); mem = HeapAlloc(GetProcessHeap(), 0, 0);
@ -75,6 +78,15 @@ START_TEST(heap)
gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE); gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE);
ok(gbl == NULL, "global realloc allocated memory\n"); 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 */ /* Local*() functions */
gbl = LocalAlloc(LMEM_MOVEABLE, 0); gbl = LocalAlloc(LMEM_MOVEABLE, 0);
ok(gbl != NULL, "local memory not allocated for size 0\n"); ok(gbl != NULL, "local memory not allocated for size 0\n");
@ -96,6 +108,15 @@ START_TEST(heap)
gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE); gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE);
ok(gbl == NULL, "local realloc allocated memory\n"); 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 */ /* trying to lock empty memory should give an error */
gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0); gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0);
ok(gbl != NULL, "returned NULL\n"); ok(gbl != NULL, "returned NULL\n");