check all os_commit calls and return NULL on failure

This commit is contained in:
Daan 2025-06-03 12:20:02 -07:00
parent 30a17bf1b7
commit 21425bc334
4 changed files with 27 additions and 14 deletions

View file

@ -163,13 +163,13 @@ bool _mi_os_has_overcommit(void);
bool _mi_os_has_virtual_reserve(void); bool _mi_os_has_virtual_reserve(void);
bool _mi_os_reset(void* addr, size_t size); bool _mi_os_reset(void* addr, size_t size);
bool _mi_os_commit(void* p, size_t size, bool* is_zero);
bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size);
bool _mi_os_decommit(void* addr, size_t size); bool _mi_os_decommit(void* addr, size_t size);
bool _mi_os_protect(void* addr, size_t size);
bool _mi_os_unprotect(void* addr, size_t size); bool _mi_os_unprotect(void* addr, size_t size);
bool _mi_os_purge(void* p, size_t size); bool _mi_os_purge(void* p, size_t size);
bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stat_size); bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stat_size);
mi_decl_nodiscard bool _mi_os_commit(void* p, size_t size, bool* is_zero);
mi_decl_nodiscard bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size);
mi_decl_nodiscard bool _mi_os_protect(void* addr, size_t size);
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid); void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid);
void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_memid_t* memid); void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_memid_t* memid);

View file

@ -300,7 +300,10 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
// explicitly commit only the aligned part // explicitly commit only the aligned part
if (commit) { if (commit) {
_mi_os_commit(p, size, NULL); if (!_mi_os_commit(p, size, NULL)) {
mi_os_prim_free(p, over_size, 0);
return NULL;
}
} }
} }
else { // mmap can free inside an allocation else { // mmap can free inside an allocation

View file

@ -37,7 +37,7 @@ static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_sta
} }
static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld); static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld);
static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld); static bool mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld);
#if (MI_DEBUG>=3) #if (MI_DEBUG>=3)
static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) { static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) {
@ -630,14 +630,14 @@ static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, co
// Note: we also experimented with "bump" allocation on the first // Note: we also experimented with "bump" allocation on the first
// allocations but this did not speed up any benchmark (due to an // allocations but this did not speed up any benchmark (due to an
// extra test in malloc? or cache effects?) // extra test in malloc? or cache effects?)
static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) { static bool mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) {
mi_assert_expensive(mi_page_is_valid_init(page)); mi_assert_expensive(mi_page_is_valid_init(page));
#if (MI_SECURE<=2) #if (MI_SECURE<=2)
mi_assert(page->free == NULL); mi_assert(page->free == NULL);
mi_assert(page->local_free == NULL); mi_assert(page->local_free == NULL);
if (page->free != NULL) return; if (page->free != NULL) return true;
#endif #endif
if (page->capacity >= page->reserved) return; if (page->capacity >= page->reserved) return true;
size_t page_size; size_t page_size;
//uint8_t* page_start = //uint8_t* page_start =
@ -673,6 +673,7 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld)
page->capacity += (uint16_t)extend; page->capacity += (uint16_t)extend;
mi_stat_increase(tld->stats.page_committed, extend * bsize); mi_stat_increase(tld->stats.page_committed, extend * bsize);
mi_assert_expensive(mi_page_is_valid_init(page)); mi_assert_expensive(mi_page_is_valid_init(page));
return true;
} }
// Initialize a fresh page // Initialize a fresh page
@ -724,9 +725,11 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
mi_assert_expensive(mi_page_is_valid_init(page)); mi_assert_expensive(mi_page_is_valid_init(page));
// initialize an initial free list // initialize an initial free list
mi_page_extend_free(heap,page,tld); if (mi_page_extend_free(heap,page,tld)) {
mi_assert(mi_page_immediate_available(page)); mi_assert(mi_page_immediate_available(page));
} }
return;
}
/* ----------------------------------------------------------- /* -----------------------------------------------------------
@ -817,9 +820,14 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p
if (page_candidate != NULL) { if (page_candidate != NULL) {
page = page_candidate; page = page_candidate;
} }
if (page != NULL && !mi_page_immediate_available(page)) { if (page != NULL) {
if (!mi_page_immediate_available(page)) {
mi_assert_internal(mi_page_is_expandable(page)); mi_assert_internal(mi_page_is_expandable(page));
mi_page_extend_free(heap, page, heap->tld); if (!mi_page_extend_free(heap, page, heap->tld)) {
page = NULL; // failed to extend
}
}
mi_assert_internal(page == NULL || mi_page_immediate_available(page));
} }
if (page == NULL) { if (page == NULL) {

View file

@ -182,7 +182,9 @@ static bool mi_page_not_in_queue(const mi_page_t* page, mi_segments_tld_t* tld)
static void mi_segment_protect_range(void* p, size_t size, bool protect) { static void mi_segment_protect_range(void* p, size_t size, bool protect) {
if (protect) { if (protect) {
_mi_os_protect(p, size); if (!_mi_os_protect(p, size)) {
_mi_error_message(EFAULT,"unable to protect segment memory at %p\n", p);
}
} }
else { else {
_mi_os_unprotect(p, size); _mi_os_unprotect(p, size);