Skip to content

Commit c6204ac

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix GH-9650: Can't initialize heap: [0x000001e7]
2 parents 8d37a65 + 8d65c2f commit c6204ac

File tree

2 files changed

+70
-44
lines changed

2 files changed

+70
-44
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ PHP NEWS
88
. Fixed bug GH-9918 (License information for xxHash is not included in
99
README.REDIST.BINS file). (Akama Hitoshi)
1010
. Fixed bug GH-9890 (OpenSSL legacy providers not available on Windows). (cmb)
11+
. Fixed bug GH-9650 (Can't initialize heap: [0x000001e7]). (Michael Voříšek)
1112

1213
- Pcntl:
1314
. Fixed bug GH-9298 (Signal handler called after rshutdown leads to crash).

Zend/zend_alloc.c

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,61 @@ stderr_last_error(char *msg)
417417
/* OS Allocation */
418418
/*****************/
419419

420+
static void zend_mm_munmap(void *addr, size_t size)
421+
{
422+
#ifdef _WIN32
423+
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
424+
/** ERROR_INVALID_ADDRESS is expected when addr is not range start address */
425+
if (GetLastError() != ERROR_INVALID_ADDRESS) {
426+
#if ZEND_MM_ERROR
427+
stderr_last_error("VirtualFree() failed");
428+
#endif
429+
return;
430+
}
431+
SetLastError(0);
432+
433+
MEMORY_BASIC_INFORMATION mbi;
434+
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0) {
435+
#if ZEND_MM_ERROR
436+
stderr_last_error("VirtualQuery() failed");
437+
#endif
438+
return;
439+
}
440+
addr = mbi.AllocationBase;
441+
442+
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
443+
#if ZEND_MM_ERROR
444+
stderr_last_error("VirtualFree() failed");
445+
#endif
446+
}
447+
}
448+
#else
449+
if (munmap(addr, size) != 0) {
450+
#if ZEND_MM_ERROR
451+
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
452+
#endif
453+
}
454+
#endif
455+
}
456+
420457
#ifndef HAVE_MREMAP
421458
static void *zend_mm_mmap_fixed(void *addr, size_t size)
422459
{
423460
#ifdef _WIN32
424-
return VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
461+
void *ptr = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
462+
463+
if (ptr == NULL) {
464+
/** ERROR_INVALID_ADDRESS is expected when fixed addr range is not free */
465+
if (GetLastError() != ERROR_INVALID_ADDRESS) {
466+
#if ZEND_MM_ERROR
467+
stderr_last_error("VirtualAlloc() fixed failed");
468+
#endif
469+
}
470+
SetLastError(0);
471+
return NULL;
472+
}
473+
ZEND_ASSERT(ptr == addr);
474+
return ptr;
425475
#else
426476
int flags = MAP_PRIVATE | MAP_ANON;
427477
#if defined(MAP_EXCL)
@@ -434,15 +484,11 @@ static void *zend_mm_mmap_fixed(void *addr, size_t size)
434484

435485
if (ptr == MAP_FAILED) {
436486
#if ZEND_MM_ERROR && !defined(MAP_EXCL) && !defined(MAP_TRYFIXED)
437-
fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
487+
fprintf(stderr, "\nmmap() fixed failed: [%d] %s\n", errno, strerror(errno));
438488
#endif
439489
return NULL;
440490
} else if (ptr != addr) {
441-
if (munmap(ptr, size) != 0) {
442-
#if ZEND_MM_ERROR
443-
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
444-
#endif
445-
}
491+
zend_mm_munmap(ptr, size);
446492
return NULL;
447493
}
448494
return ptr;
@@ -495,23 +541,6 @@ static void *zend_mm_mmap(size_t size)
495541
#endif
496542
}
497543

498-
static void zend_mm_munmap(void *addr, size_t size)
499-
{
500-
#ifdef _WIN32
501-
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
502-
#if ZEND_MM_ERROR
503-
stderr_last_error("VirtualFree() failed");
504-
#endif
505-
}
506-
#else
507-
if (munmap(addr, size) != 0) {
508-
#if ZEND_MM_ERROR
509-
fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
510-
#endif
511-
}
512-
#endif
513-
}
514-
515544
/***********/
516545
/* Bitmask */
517546
/***********/
@@ -704,13 +733,21 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
704733
zend_mm_munmap(ptr, size);
705734
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
706735
#ifdef _WIN32
707-
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
708-
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
709-
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
710736
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
711737
if (offset != 0) {
712-
zend_mm_munmap(ptr, size);
713-
return NULL;
738+
offset = alignment - offset;
739+
}
740+
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
741+
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + offset), size);
742+
if (ptr == NULL) { // fix GH-9650, fixed addr range is not free
743+
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
744+
if (ptr == NULL) {
745+
return NULL;
746+
}
747+
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
748+
if (offset != 0) {
749+
ptr = (void*)((char*)ptr + alignment - offset);
750+
}
714751
}
715752
return ptr;
716753
#else
@@ -1867,11 +1904,7 @@ static zend_mm_heap *zend_mm_init(void)
18671904

18681905
if (UNEXPECTED(chunk == NULL)) {
18691906
#if ZEND_MM_ERROR
1870-
#ifdef _WIN32
1871-
stderr_last_error("Can't initialize heap");
1872-
#else
1873-
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
1874-
#endif
1907+
fprintf(stderr, "Can't initialize heap\n");
18751908
#endif
18761909
return NULL;
18771910
}
@@ -3017,11 +3050,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
30173050
chunk = (zend_mm_chunk*)handlers->chunk_alloc(&tmp_storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
30183051
if (UNEXPECTED(chunk == NULL)) {
30193052
#if ZEND_MM_ERROR
3020-
#ifdef _WIN32
3021-
stderr_last_error("Can't initialize heap");
3022-
#else
3023-
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
3024-
#endif
3053+
fprintf(stderr, "Can't initialize heap\n");
30253054
#endif
30263055
return NULL;
30273056
}
@@ -3064,11 +3093,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
30643093
if (!storage) {
30653094
handlers->chunk_free(&tmp_storage, chunk, ZEND_MM_CHUNK_SIZE);
30663095
#if ZEND_MM_ERROR
3067-
#ifdef _WIN32
3068-
stderr_last_error("Can't initialize heap");
3069-
#else
3070-
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
3071-
#endif
3096+
fprintf(stderr, "Can't initialize heap\n");
30723097
#endif
30733098
return NULL;
30743099
}

0 commit comments

Comments
 (0)