Module: wine Branch: master Commit: d5b22ae0853ddd3ea32b7e71f425b140d6864dd4 URL: https://gitlab.winehq.org/wine/wine/-/commit/d5b22ae0853ddd3ea32b7e71f425b14...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Jun 7 11:46:21 2023 +0200
ntdll: Support adding overlapping ranges in mmap_add_reserved_area().
---
dlls/ntdll/unix/virtual.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index b208d7d8e9b..0ccb8cdfbfa 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -244,42 +244,43 @@ void *anon_mmap_alloc( size_t size, int prot ) static void mmap_add_reserved_area( void *addr, SIZE_T size ) { struct reserved_area *area; - struct list *ptr; + struct list *ptr, *next; + void *end, *area_end;
if (!((intptr_t)addr + size)) size--; /* avoid wrap-around */ + end = (char *)addr + size;
LIST_FOR_EACH( ptr, &reserved_areas ) { area = LIST_ENTRY( ptr, struct reserved_area, entry ); + area_end = (char *)area->base + area->size; + + if (area->base > end) break; + if (area_end < addr) continue; if (area->base > addr) { - /* try to merge with the next one */ - if ((char *)addr + size == (char *)area->base) - { - area->base = addr; - area->size += size; - return; - } - break; + area->size += (char *)area->base - (char *)addr; + area->base = addr; } - else if ((char *)area->base + area->size == (char *)addr) + if (area_end >= end) return; + + /* try to merge with the following ones */ + while ((next = list_next( &reserved_areas, ptr ))) { - /* merge with the previous one */ - area->size += size; + struct reserved_area *area_next = LIST_ENTRY( next, struct reserved_area, entry ); + void *next_end = (char *)area_next->base + area_next->size;
- /* try to merge with the next one too */ - if ((ptr = list_next( &reserved_areas, ptr ))) + if (area_next->base > end) break; + list_remove( next ); + free( area_next ); + if (next_end >= end) { - struct reserved_area *next = LIST_ENTRY( ptr, struct reserved_area, entry ); - if ((char *)addr + size == (char *)next->base) - { - area->size += next->size; - list_remove( &next->entry ); - free( next ); - } + end = next_end; + break; } - return; } + area->size = (char *)end - (char *)area->base; + return; }
if ((area = malloc( sizeof(*area) )))