Skip to content

Commit 5a99eee

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

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

Zend/zend_alloc.c

Lines changed: 32 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,9 +448,13 @@ 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
}
448460
return ptr;
@@ -686,14 +698,28 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
686698
zend_mm_munmap(ptr, size);
687699
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
688700
#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);
692701
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
693702
if (offset != 0) {
694-
zend_mm_munmap(ptr, size);
695-
return NULL;
703+
offset = alignment - offset;
696704
}
705+
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
706+
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + offset), size);
707+
if (ptr == NULL) { // GH-9650, fixed addr range is not free
708+
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
709+
if (ptr == NULL) {
710+
return NULL;
711+
}
712+
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
713+
if (offset != 0) {
714+
ptr += alignment - offset;
715+
}
716+
} else {
717+
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
718+
if (offset != 0) {
719+
zend_mm_munmap(ptr, size);
720+
return NULL;
721+
}
722+
}
697723
return ptr;
698724
#else
699725
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);

0 commit comments

Comments
 (0)