Fix GH-9650: Can't initialize heap: [0x000001e7]

Closes GH-9721.
This commit is contained in:
Michael Voříšek 2022-11-14 15:16:31 +01:00 committed by Christoph M. Becker
parent c53b065c48
commit 8d65c2fee5
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
2 changed files with 70 additions and 44 deletions

1
NEWS
View file

@ -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

View file

@ -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)
@ -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;
@ -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 */
/***********/
@ -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
@ -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;
}
@ -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;
}
@ -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;
}