diff --git a/CMakeLists.txt b/CMakeLists.txt index 079d2063..707dd819 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ option(MI_OVERRIDE "Override the standard malloc interface (e.g. define option(MI_XMALLOC "Enable abort() call on memory allocation failure by default" OFF) option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF) option(MI_VALGRIND "Compile with Valgrind support (adds a small overhead)" OFF) +option(MI_ASAN "Compile with address sanitizer support (adds a small overhead)" OFF) option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) option(MI_SEE_ASM "Generate assembly files" OFF) option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON) @@ -139,6 +140,25 @@ if(MI_VALGRIND) endif() endif() +if(MI_ASAN) + if (MI_VALGRIND) + set(MI_ASAN OFF) + message(WARNING "Cannot enable address sanitizer support with also Valgrind support enabled (MI_ASAN=OFF)") + else() + CHECK_INCLUDE_FILES("sanitizer/asan_interface.h" MI_HAS_ASANH) + if (NOT MI_HAS_ASANH) + set(MI_ASAN OFF) + message(WARNING "Cannot find the 'sanitizer/asan_interface.h' -- install address sanitizer support first") + message(STATUS "Compile **without** address sanitizer support (MI_ASAN=OFF)") + else() + message(STATUS "Compile with address sanitizer support (MI_ASAN=ON)") + list(APPEND mi_defines MI_ASAN=1) + list(APPEND mi_cflags -fsanitize=address) + list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=address) + endif() + endif() +endif() + if(MI_SEE_ASM) message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)") list(APPEND mi_cflags -save-temps) @@ -296,6 +316,9 @@ if(MI_SECURE) endif() if(MI_VALGRIND) set(mi_basename "${mi_basename}-valgrind") +endif() +if(MI_ASAN) + set(mi_basename "${mi_basename}-asan") endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC) if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel|none)$")) diff --git a/include/mimalloc-track.h b/include/mimalloc-track.h index bb9df4fa..3bb9527c 100644 --- a/include/mimalloc-track.h +++ b/include/mimalloc-track.h @@ -10,12 +10,13 @@ terms of the MIT license. A copy of the license can be found in the file // ------------------------------------------------------ // Track memory ranges with macros for tools like Valgrind -// or other memory checkers. +// address sanitizer, or other memory checkers. // ------------------------------------------------------ #if MI_VALGRIND #define MI_TRACK_ENABLED 1 +#define MI_TRACK_TOOL "valgrind" #include #include @@ -23,17 +24,35 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_track_malloc(p,size,zero) VALGRIND_MALLOCLIKE_BLOCK(p,size,MI_PADDING_SIZE /*red zone*/,zero) #define mi_track_resize(p,oldsize,newsize) VALGRIND_RESIZEINPLACE_BLOCK(p,oldsize,newsize,MI_PADDING_SIZE /*red zone*/) #define mi_track_free(p) VALGRIND_FREELIKE_BLOCK(p,MI_PADDING_SIZE /*red zone*/) +#define mi_track_free_size(p,_size) mi_track_free(p) #define mi_track_mem_defined(p,size) VALGRIND_MAKE_MEM_DEFINED(p,size) #define mi_track_mem_undefined(p,size) VALGRIND_MAKE_MEM_UNDEFINED(p,size) #define mi_track_mem_noaccess(p,size) VALGRIND_MAKE_MEM_NOACCESS(p,size) +#elif MI_ASAN + +#define MI_TRACK_ENABLED 1 +#define MI_TRACK_TOOL "asan" + +#include + +#define mi_track_malloc(p,size,zero) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_resize(p,oldsize,newsize) ASAN_POISON_MEMORY_REGION(p,oldsize); ASAN_UNPOISON_MEMORY_REGION(p,newsize) +#define mi_track_free(p) ASAN_POISON_MEMORY_REGION(p,mi_usable_size(p)) +#define mi_track_free_size(p,size) ASAN_POISON_MEMORY_REGION(p,size) +#define mi_track_mem_defined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_undefined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_noaccess(p,size) ASAN_POISON_MEMORY_REGION(p,size) + #else #define MI_TRACK_ENABLED 0 +#define MI_TRACK_TOOL "none" #define mi_track_malloc(p,size,zero) #define mi_track_resize(p,oldsize,newsize) -#define mi_track_free(p) +#define mi_track_free(p,size) +#define mi_track_free_size(p,_size) #define mi_track_mem_defined(p,size) #define mi_track_mem_undefined(p,size) #define mi_track_mem_noaccess(p,size) diff --git a/include/mimalloc.h b/include/mimalloc.h index fd287227..60c5c791 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -541,7 +541,7 @@ template struct mi_heap_destroy_stl_allocator : public _mi_heap_stl_all template mi_heap_destroy_stl_allocator(const mi_heap_destroy_stl_allocator& x) mi_attr_noexcept : _mi_heap_stl_allocator_common(x) { } mi_heap_destroy_stl_allocator select_on_container_copy_construction() const { return *this; } - void deallocate(T* p, size_type) { /* do nothing as we destroy the heap on destruct. */ } + void deallocate(T*, size_type) { /* do nothing as we destroy the heap on destruct. */ } template struct rebind { typedef mi_heap_destroy_stl_allocator other; }; }; diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 86358612..c9404660 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -78,7 +78,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t* #if MI_TRACK_ENABLED if (p != aligned_p) { - mi_track_free(p); + mi_track_free_size(p, oversize); mi_track_malloc(aligned_p, size, zero); } else { diff --git a/src/alloc.c b/src/alloc.c index ac117f17..48c1fffb 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -702,7 +702,7 @@ void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL (with size 0) if mi_unlikely(newsize <= size && newsize >= (size / 2) && newsize > 0) { // note: newsize must be > 0 or otherwise we return NULL for realloc(NULL,0) // todo: adjust potential padding to reflect the new size? - mi_track_free(p); + mi_track_free_size(p, size); mi_track_malloc(p,newsize,true); return p; // reallocation still fits and not more than 50% waste } diff --git a/src/init.c b/src/init.c index 18eadf1f..e727f39c 100644 --- a/src/init.c +++ b/src/init.c @@ -587,6 +587,7 @@ void mi_process_init(void) mi_attr_noexcept { _mi_verbose_message("debug level : %d\n", MI_DEBUG); #endif _mi_verbose_message("secure level: %d\n", MI_SECURE); + _mi_verbose_message("mem tracking: %s\n", MI_TRACK_TOOL); mi_thread_init(); #if defined(_WIN32) && !defined(MI_SHARED_LIB) diff --git a/src/options.c b/src/options.c index 6980a047..40fe8993 100644 --- a/src/options.c +++ b/src/options.c @@ -107,7 +107,8 @@ void _mi_options_init(void) { for(int i = 0; i < _mi_option_last; i++ ) { mi_option_t option = (mi_option_t)i; long l = mi_option_get(option); MI_UNUSED(l); // initialize - if (option != mi_option_verbose) { + // if (option != mi_option_verbose) + { mi_option_desc_t* desc = &options[option]; _mi_verbose_message("option '%s': %ld\n", desc->name, desc->value); } diff --git a/test/test-wrong.c b/test/test-wrong.c index 8bf7767e..6c3d5a74 100644 --- a/test/test-wrong.c +++ b/test/test-wrong.c @@ -31,9 +31,9 @@ terms of the MIT license. A copy of the license can be found in the file #endif int main(int argc, char** argv) { - int* p = mi(malloc)(3*sizeof(int)); + int* p = (int*)mi(malloc)(3*sizeof(int)); - int* r = mi_malloc_aligned(8,16); + int* r = (int*)mi_malloc_aligned(8,16); mi_free(r); // illegal byte wise read @@ -42,7 +42,7 @@ int main(int argc, char** argv) { mi(free)(c); // undefined access - int* q = mi(malloc)(sizeof(int)); + int* q = (int*)mi(malloc)(sizeof(int)); printf("undefined: %d\n", *q); // illegal int read