diff --git a/include/mimalloc/bits.h b/include/mimalloc/bits.h index 371cb7ce..e3038d11 100644 --- a/include/mimalloc/bits.h +++ b/include/mimalloc/bits.h @@ -123,13 +123,17 @@ typedef int32_t mi_ssize_t; // use a flat page-map (or a 2-level one) #ifndef MI_PAGE_MAP_FLAT -#if MI_MAX_VABITS <= 40 && !defined(__APPLE__) +#if MI_MAX_VABITS <= 40 && !MI_SECURE && !defined(__APPLE__) #define MI_PAGE_MAP_FLAT 1 #else #define MI_PAGE_MAP_FLAT 0 #endif #endif +#if MI_PAGE_MAP_FLAT && MI_SECURE +#error should not use MI_PAGE_MAP_FLAT with a secure build +#endif + /* -------------------------------------------------------------------------------- Builtin's diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 98908281..fad73521 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -589,7 +589,7 @@ static inline mi_page_t* _mi_checked_ptr_page(const void* p) { static inline mi_page_t* _mi_ptr_page(const void* p) { mi_assert_internal(p==NULL || mi_is_in_heap_region(p)); - #if MI_DEBUG || defined(__APPLE__) + #if MI_DEBUG || MI_SECURE || defined(__APPLE__) return _mi_checked_ptr_page(p); #else return _mi_unchecked_ptr_page(p); diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 86aeb07f..71b2c93b 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -50,7 +50,7 @@ terms of the MIT license. A copy of the license can be found in the file // Define MI_SECURE to enable security mitigations. Level 1 has minimal performance impact, // but protects most metadata with guard pages: -// #define MI_SECURE 1 // guard page around metadata +// #define MI_SECURE 1 // guard page around metadata; check pointer validity on free // // Level 2 has more performance impact but protect well against various buffer overflows // by surrounding all mimalloc pages with guard pages: diff --git a/src/page-map.c b/src/page-map.c index 6066336e..f80e4226 100644 --- a/src/page-map.c +++ b/src/page-map.c @@ -202,8 +202,12 @@ bool _mi_page_map_init(void) { const size_t page_map_size = _mi_align_up( mi_page_map_count * sizeof(mi_page_t**), os_page_size); const size_t submap_size = MI_PAGE_MAP_SUB_SIZE; const size_t reserve_size = page_map_size + submap_size; + #if MI_SECURE + const bool commit = true; // the whole page map is valid and we can reliably check any pointer + #else const bool commit = page_map_size <= 64*MI_KiB || mi_option_is_enabled(mi_option_pagemap_commit) || _mi_os_has_overcommit(); + #endif _mi_page_map = (_Atomic(mi_page_t**)*)_mi_os_alloc_aligned(reserve_size, 1, commit, true /* allow large */, &mi_page_map_memid); if (_mi_page_map==NULL) { _mi_error_message(ENOMEM, "unable to reserve virtual memory for the page map (%zu KiB)\n", page_map_size / MI_KiB); diff --git a/test/test-api.c b/test/test-api.c index 9aa84b61..9ed66a38 100644 --- a/test/test-api.c +++ b/test/test-api.c @@ -89,9 +89,11 @@ int main(void) { CHECK_BODY("malloc-free-null") { mi_free(NULL); }; + #if MI_INTPTR_BITS >= 64 CHECK_BODY("malloc-free-invalid-low") { mi_free((void*)(MI_ZU(0x0000000003990080))); // issue #1087 }; + #endif CHECK_BODY("calloc-overflow") { // use (size_t)&mi_calloc to get some number without triggering compiler warnings result = (mi_calloc((size_t)&mi_calloc,SIZE_MAX/1000) == NULL);