Skip to content

Commit fb58591

Browse files
committed
Fix the JIT buffer relocation failure at the corner case
Avoids missing possible candidates due to the large address range of the free segment. Eg,  48000000-49400000 r-xs 08000000 00:0f 39322841               segment1 7ffff2ec8000-7ffff2f49000 rw-p 00000000 00:00 0              segment2 7ffff6fae000-7ffff735c000 r-xp 00200000 08:02 11538515       /usr/local/sbin/php-fpm original code will miss the opportunity between [7ffff2ec** - 7ffff2ec8000]. Fix issue #11265. Signed-off-by: Long, Tao <[email protected]>
1 parent 8d0345d commit fb58591

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

ext/opcache/shared_alloc_mmap.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@
5252
static void *find_prefered_mmap_base(size_t requested_size)
5353
{
5454
size_t huge_page_size = 2 * 1024 * 1024;
55-
uintptr_t last_free_addr = 0;
5655
uintptr_t last_candidate = (uintptr_t)MAP_FAILED;
5756
uintptr_t start, end, text_start = 0;
57+
5858
#if defined(__linux__)
5959
FILE *f;
60+
uintptr_t last_candidate_end = 0;
61+
uintptr_t pre_seg_end = 0;
6062
char buffer[MAXPATHLEN];
6163

6264
f = fopen("/proc/self/maps", "r");
@@ -67,14 +69,15 @@ static void *find_prefered_mmap_base(size_t requested_size)
6769
while (fgets(buffer, MAXPATHLEN, f) && sscanf(buffer, "%lx-%lx", &start, &end) == 2) {
6870
if ((uintptr_t)execute_ex >= start) {
6971
/* the current segment lays before PHP .text segment or PHP .text segment itself */
70-
if (last_free_addr + requested_size <= start) {
71-
last_candidate = last_free_addr;
72+
if (start - pre_seg_end >= requested_size + huge_page_size) {
73+
last_candidate = start - requested_size - huge_page_size;
74+
last_candidate = ZEND_MM_ALIGNED_SIZE_EX(last_candidate, huge_page_size);
7275
}
7376
if ((uintptr_t)execute_ex < end) {
7477
/* the current segment is PHP .text segment itself */
7578
if (last_candidate != (uintptr_t)MAP_FAILED) {
7679
if (end - last_candidate < UINT32_MAX) {
77-
/* we have found a big enough hole before the text segment */
80+
/* we have found a big enough hole before the .text segment */
7881
break;
7982
}
8083
last_candidate = (uintptr_t)MAP_FAILED;
@@ -83,20 +86,22 @@ static void *find_prefered_mmap_base(size_t requested_size)
8386
}
8487
} else {
8588
/* the current segment lays after PHP .text segment */
86-
if (last_free_addr + requested_size - text_start > UINT32_MAX) {
89+
last_candidate_end = pre_seg_end + requested_size + huge_page_size;
90+
if (last_candidate_end - text_start > UINT32_MAX) {
8791
/* the current segment and the following segments lay too far from PHP .text segment */
8892
break;
8993
}
90-
if (last_free_addr + requested_size <= start) {
91-
last_candidate = last_free_addr;
94+
if (last_candidate_end <= start) {
95+
last_candidate = ZEND_MM_ALIGNED_SIZE_EX(pre_seg_end, huge_page_size);
9296
break;
9397
}
9498
}
95-
last_free_addr = ZEND_MM_ALIGNED_SIZE_EX(end, huge_page_size);
99+
pre_seg_end = end;
96100

97101
}
98102
fclose(f);
99103
#elif defined(__FreeBSD__)
104+
uintptr_t last_free_addr = 0;
100105
size_t s = 0;
101106
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
102107
if (sysctl(mib, 4, NULL, &s, NULL, 0) == 0) {

0 commit comments

Comments
 (0)