Issue #876: Fix integer overflow on slice_count

If the slice count doesn't fit into uint32_t, consider that the
memory allocation failed.

On Linux s390x, allocating around 8,589,934,592 GiB with mmap() works
thanks to overcommit on a machine with 8 GiB of memory:

    mmap(NULL,
         0x8000000000400000,
         PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
         -1, 0)
This commit is contained in:
Victor Stinner 2024-04-15 10:36:47 +02:00
parent f199b888b4
commit 84ceba4a41

View file

@ -820,6 +820,9 @@ static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment
const size_t extra = align_offset - info_size; const size_t extra = align_offset - info_size;
// recalculate due to potential guard pages // recalculate due to potential guard pages
*psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices); *psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices);
// gh-876: mi_page_t.slice_count type is uint32_t
if (*psegment_slices > (size_t)UINT32_MAX) return NULL;
} }
const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE; const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE;
@ -870,6 +873,9 @@ static mi_segment_t* mi_segment_alloc(size_t required, size_t page_alignment, mi
size_t pre_size; size_t pre_size;
size_t segment_slices = mi_segment_calculate_slices(required, &pre_size, &info_slices); size_t segment_slices = mi_segment_calculate_slices(required, &pre_size, &info_slices);
// gh-876: mi_page_t.slice_count type is uint32_t
if (segment_slices > (size_t)UINT32_MAX) return NULL;
// Commit eagerly only if not the first N lazy segments (to reduce impact of many threads that allocate just a little) // Commit eagerly only if not the first N lazy segments (to reduce impact of many threads that allocate just a little)
const bool eager_delay = (// !_mi_os_has_overcommit() && // never delay on overcommit systems const bool eager_delay = (// !_mi_os_has_overcommit() && // never delay on overcommit systems
_mi_current_thread_count() > 1 && // do not delay for the first N threads _mi_current_thread_count() > 1 && // do not delay for the first N threads