From 6c572f9ab3d028dbc399fc97ff8d8a9835be20fe Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 30 May 2014 12:02:55 +0300 Subject: [PATCH] Enhance error checking in heap allocation routines on MS-Windows. src/w32heap.c (malloc_before_dump, malloc_after_dump) (malloc_before_dump, realloc_after_dump, realloc_before_dump) (mmap_alloc, mmap_realloc): Check for errors more thoroughly and set errno where appropriate to emulate CRT functions. --- src/ChangeLog | 7 +++++++ src/w32heap.c | 62 ++++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index a4f1cb7590a..a9b1e8e3f4d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2014-05-30 Eli Zaretskii + + * w32heap.c (malloc_before_dump, malloc_after_dump) + (malloc_before_dump, realloc_after_dump, realloc_before_dump) + (mmap_alloc, mmap_realloc): Check for errors more thoroughly and + set errno where appropriate to emulate CRT functions. + 2014-05-30 Dmitry Antipov Debugging facility to check whether 'const char *' points to diff --git a/src/w32heap.c b/src/w32heap.c index be097901747..cc08dc37219 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -47,6 +47,7 @@ #include #include +#include #include #include "w32common.h" @@ -241,7 +242,8 @@ init_heap (void) if (s_pfn_Heap_Set_Information ((PVOID) heap, HeapCompatibilityInformation, &enable_lfh, sizeof(enable_lfh)) == 0) - DebPrint (("Enabling Low Fragmentation Heap failed\n")); + DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", + GetLastError ())); #endif the_malloc_fn = malloc_after_dump; @@ -298,7 +300,10 @@ malloc_after_dump (size_t size) void *p = HeapAlloc (heap, 0, size); /* After dump, keep track of the last allocated byte for sbrk(0). */ - data_region_end = p + size - 1; + if (p) + data_region_end = p + size - 1; + else + errno = ENOMEM; return p; } @@ -313,6 +318,8 @@ malloc_before_dump (size_t size) { /* Use the private heap if possible. */ p = HeapAlloc (heap, 0, size); + if (!p) + errno = ENOMEM; } else { @@ -371,16 +378,22 @@ realloc_after_dump (void *ptr, size_t size) { /* Reallocate the block since it lies in the new heap. */ p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; } else { /* If the block lies in the dumped data, do not free it. Only allocate a new one. */ p = HeapAlloc (heap, 0, size); - CopyMemory (p, ptr, size); + if (p) + CopyMemory (p, ptr, size); + else + errno = ENOMEM; } /* After dump, keep track of the last allocated byte for sbrk(0). */ - data_region_end = p + size - 1; + if (p) + data_region_end = p + size - 1; return p; } @@ -392,7 +405,11 @@ realloc_before_dump (void *ptr, size_t size) /* Before dumping. */ if (dumped_data < (unsigned char *)ptr && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize) - p = HeapReAlloc (heap, 0, ptr, size); + { + p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; + } else { /* In this case, either the new block is too large for the heap, @@ -400,8 +417,11 @@ realloc_before_dump (void *ptr, size_t size) malloc_before_dump() and free_before_dump() will take care of reallocation. */ p = malloc_before_dump (size); - CopyMemory (p, ptr, size); - free_before_dump (ptr); + if (p) + { + CopyMemory (p, ptr, size); + free_before_dump (ptr); + } } return p; } @@ -508,8 +528,16 @@ mmap_alloc (void **var, size_t nbytes) *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); } - if (!p && GetLastError () != ERROR_NOT_ENOUGH_MEMORY) - DebPrint (("mmap_alloc: error %ld\n", GetLastError())); + if (!p) + { + if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY) + errno = ENOMEM; + else + { + DebPrint (("mmap_alloc: error %ld\n", GetLastError ())); + errno = EINVAL; + } + } return *var = p; } @@ -520,7 +548,7 @@ mmap_free (void **var) if (*var) { if (VirtualFree (*var, 0, MEM_RELEASE) == 0) - DebPrint (("mmap_free: error %ld\n", GetLastError())); + DebPrint (("mmap_free: error %ld\n", GetLastError ())); *var = NULL; } } @@ -541,13 +569,14 @@ mmap_realloc (void **var, size_t nbytes) } if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) - DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError())); + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); /* We need to enlarge the block. */ if (memInfo.RegionSize < nbytes) { if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) - DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError())); + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", + GetLastError ())); /* If there is enough room in the current reserved area, then commit more pages as needed. */ if (m2.State == MEM_RESERVE @@ -559,8 +588,11 @@ mmap_realloc (void **var, size_t nbytes) nbytes - memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE); if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) - DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", - GetLastError())); + { + DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", + GetLastError ())); + errno = ENOMEM; + } return *var; } else @@ -615,7 +647,7 @@ mmap_realloc (void **var, size_t nbytes) if (VirtualFree (*var + nbytes + get_page_size(), memInfo.RegionSize - nbytes - get_page_size(), MEM_DECOMMIT) == 0) - DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError())); + DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError ())); return *var; } -- 2.11.4.GIT