Skip to content

Commit

Permalink
Fix GH-9650: Can't initialize heap: [0x000001e7]
Browse files Browse the repository at this point in the history
Closes GH-9721.
  • Loading branch information
mvorisek authored and cmb69 committed Nov 17, 2022
1 parent c53b065 commit 8d65c2f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 44 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -7,6 +7,7 @@ PHP NEWS
(cmb)
. Fixed bug GH-9918 (License information for xxHash is not included in
README.REDIST.BINS file). (Akama Hitoshi)
. Fixed bug GH-9650 (Can't initialize heap: [0x000001e7]). (Michael Voříšek)

- MBString:
. Fixed bug GH-9535 (The behavior of mb_strcut in mbstring has been changed in
Expand Down
113 changes: 69 additions & 44 deletions Zend/zend_alloc.c
Expand Up @@ -416,11 +416,61 @@ stderr_last_error(char *msg)
/* OS Allocation */
/*****************/

static void zend_mm_munmap(void *addr, size_t size)
{
#ifdef _WIN32
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
/** ERROR_INVALID_ADDRESS is expected when addr is not range start address */
if (GetLastError() != ERROR_INVALID_ADDRESS) {
#if ZEND_MM_ERROR
stderr_last_error("VirtualFree() failed");
#endif
return;
}
SetLastError(0);

MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0) {
#if ZEND_MM_ERROR
stderr_last_error("VirtualQuery() failed");
#endif
return;
}
addr = mbi.AllocationBase;

if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
#if ZEND_MM_ERROR
stderr_last_error("VirtualFree() failed");
#endif
}
}
#else
if (munmap(addr, size) != 0) {
#if ZEND_MM_ERROR
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
#endif
}
#endif
}

#ifndef HAVE_MREMAP
static void *zend_mm_mmap_fixed(void *addr, size_t size)
{
#ifdef _WIN32
return VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
void *ptr = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

if (ptr == NULL) {
/** ERROR_INVALID_ADDRESS is expected when fixed addr range is not free */
if (GetLastError() != ERROR_INVALID_ADDRESS) {
#if ZEND_MM_ERROR
stderr_last_error("VirtualAlloc() fixed failed");
#endif
}
SetLastError(0);
return NULL;
}
ZEND_ASSERT(ptr == addr);
return ptr;
#else
int flags = MAP_PRIVATE | MAP_ANON;
#if defined(MAP_EXCL)
Expand All @@ -431,15 +481,11 @@ static void *zend_mm_mmap_fixed(void *addr, size_t size)

if (ptr == MAP_FAILED) {
#if ZEND_MM_ERROR && !defined(MAP_EXCL)
fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
fprintf(stderr, "\nmmap() fixed failed: [%d] %s\n", errno, strerror(errno));
#endif
return NULL;
} else if (ptr != addr) {
if (munmap(ptr, size) != 0) {
#if ZEND_MM_ERROR
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
#endif
}
zend_mm_munmap(ptr, size);
return NULL;
}
return ptr;
Expand Down Expand Up @@ -483,23 +529,6 @@ static void *zend_mm_mmap(size_t size)
#endif
}

static void zend_mm_munmap(void *addr, size_t size)
{
#ifdef _WIN32
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
#if ZEND_MM_ERROR
stderr_last_error("VirtualFree() failed");
#endif
}
#else
if (munmap(addr, size) != 0) {
#if ZEND_MM_ERROR
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
#endif
}
#endif
}

/***********/
/* Bitmask */
/***********/
Expand Down Expand Up @@ -682,13 +711,21 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
zend_mm_munmap(ptr, size);
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
#ifdef _WIN32
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
zend_mm_munmap(ptr, size);
return NULL;
offset = alignment - offset;
}
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + offset), size);
if (ptr == NULL) { // fix GH-9650, fixed addr range is not free
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
if (ptr == NULL) {
return NULL;
}
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
ptr = (void*)((char*)ptr + alignment - offset);
}
}
return ptr;
#else
Expand Down Expand Up @@ -1847,11 +1884,7 @@ static zend_mm_heap *zend_mm_init(void)

if (UNEXPECTED(chunk == NULL)) {
#if ZEND_MM_ERROR
#ifdef _WIN32
stderr_last_error("Can't initialize heap");
#else
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
#endif
fprintf(stderr, "Can't initialize heap\n");
#endif
return NULL;
}
Expand Down Expand Up @@ -2978,11 +3011,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
chunk = (zend_mm_chunk*)handlers->chunk_alloc(&tmp_storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
if (UNEXPECTED(chunk == NULL)) {
#if ZEND_MM_ERROR
#ifdef _WIN32
stderr_last_error("Can't initialize heap");
#else
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
#endif
fprintf(stderr, "Can't initialize heap\n");
#endif
return NULL;
}
Expand Down Expand Up @@ -3025,11 +3054,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
if (!storage) {
handlers->chunk_free(&tmp_storage, chunk, ZEND_MM_CHUNK_SIZE);
#if ZEND_MM_ERROR
#ifdef _WIN32
stderr_last_error("Can't initialize heap");
#else
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
#endif
fprintf(stderr, "Can't initialize heap\n");
#endif
return NULL;
}
Expand Down

0 comments on commit 8d65c2f

Please sign in to comment.