Skip to content

Commit 93b71b8

Browse files
committed
Fix fixed addr range alloc is not free for Windows
1 parent d8d8fd9 commit 93b71b8

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

Zend/zend_alloc.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,14 @@ stderr_last_error(char *msg)
419419
static void zend_mm_munmap(void *addr, size_t size)
420420
{
421421
#ifdef _WIN32
422+
MEMORY_BASIC_INFORMATION mbi;
423+
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0) {
424+
#if ZEND_MM_ERROR
425+
stderr_last_error("VirtualQuery() failed");
426+
#endif
427+
}
428+
addr = mbi.AllocationBase;
429+
422430
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
423431
#if ZEND_MM_ERROR
424432
stderr_last_error("VirtualFree() failed");
@@ -440,11 +448,16 @@ static void *zend_mm_mmap_fixed(void *addr, size_t size)
440448
void *ptr = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
441449

442450
if (ptr == NULL) {
451+
/** ERROR_INVALID_ADDRESS is expected when fixed addr range is not free */
452+
if (GetLastError() != ERROR_INVALID_ADDRESS) {
443453
#if ZEND_MM_ERROR
444-
stderr_last_error("VirtualAlloc() fixed failed");
454+
stderr_last_error("VirtualAlloc() fixed failed");
445455
#endif
456+
}
457+
SetLastError(0);
446458
return NULL;
447459
}
460+
ZEND_ASSERT(ptr == addr);
448461
return ptr;
449462
#else
450463
int flags = MAP_PRIVATE | MAP_ANON;
@@ -686,14 +699,28 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
686699
zend_mm_munmap(ptr, size);
687700
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
688701
#ifdef _WIN32
689-
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
690-
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
691-
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
692702
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
693703
if (offset != 0) {
694-
zend_mm_munmap(ptr, size);
695-
return NULL;
704+
offset = alignment - offset;
696705
}
706+
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
707+
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + offset), size);
708+
if (ptr == NULL) { // fix GH-9650, fixed addr range is not free
709+
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
710+
if (ptr == NULL) {
711+
return NULL;
712+
}
713+
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
714+
if (offset != 0) {
715+
ptr = (void*)((char*)ptr + alignment - offset);
716+
}
717+
} else {
718+
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
719+
if (offset != 0) {
720+
zend_mm_munmap(ptr, size);
721+
return NULL;
722+
}
723+
}
697724
return ptr;
698725
#else
699726
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);

0 commit comments

Comments
 (0)