mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-05 23:19:31 +03:00
fix false positives from valgrind in rptest
This commit is contained in:
parent
a1f5a5d962
commit
84c706508c
6 changed files with 40 additions and 26 deletions
|
@ -20,7 +20,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#include <valgrind/valgrind.h>
|
#include <valgrind/valgrind.h>
|
||||||
#include <valgrind/memcheck.h>
|
#include <valgrind/memcheck.h>
|
||||||
|
|
||||||
#define mi_track_malloc(p,size,zero) VALGRIND_MALLOCLIKE_BLOCK(p,size,MI_PADDING_SIZE /*red zone*/,(zero?1:0))
|
#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_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(p) VALGRIND_FREELIKE_BLOCK(p,MI_PADDING_SIZE /*red zone*/)
|
||||||
#define mi_track_mem_defined(p,size) VALGRIND_MAKE_MEM_DEFINED(p,size)
|
#define mi_track_mem_defined(p,size) VALGRIND_MAKE_MEM_DEFINED(p,size)
|
||||||
|
|
|
@ -66,7 +66,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
|
|
||||||
// Encoded free lists allow detection of corrupted free lists
|
// Encoded free lists allow detection of corrupted free lists
|
||||||
// and can detect buffer overflows, modify after free, and double `free`s.
|
// and can detect buffer overflows, modify after free, and double `free`s.
|
||||||
#if (MI_SECURE>=3 || MI_DEBUG>=1 || MI_PADDING > 0)
|
#if (MI_SECURE>=3 || MI_DEBUG>=1 || MI_PADDING > 0) && !MI_VALGRIND
|
||||||
#define MI_ENCODE_FREELIST 1
|
#define MI_ENCODE_FREELIST 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,10 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t*
|
||||||
mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0);
|
mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0);
|
||||||
mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p), _mi_ptr_page(aligned_p), aligned_p));
|
mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p), _mi_ptr_page(aligned_p), aligned_p));
|
||||||
|
|
||||||
mi_track_free(p);
|
if (p != aligned_p) {
|
||||||
mi_track_malloc(aligned_p,size,zero);
|
mi_track_free(p);
|
||||||
|
mi_track_malloc(aligned_p,size,zero);
|
||||||
|
}
|
||||||
return aligned_p;
|
return aligned_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t;
|
||||||
// Override system malloc
|
// Override system malloc
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) && !defined(MI_VALGRIND)
|
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) && !MI_TRACK_ENABLED
|
||||||
// gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions
|
// gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions
|
||||||
#if (defined(__GNUC__) && __GNUC__ >= 9)
|
#if (defined(__GNUC__) && __GNUC__ >= 9)
|
||||||
#pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward
|
#pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward
|
||||||
|
@ -44,7 +44,7 @@ typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t;
|
||||||
#define MI_FORWARD02(fun,x,y) MI_FORWARD(fun)
|
#define MI_FORWARD02(fun,x,y) MI_FORWARD(fun)
|
||||||
#else
|
#else
|
||||||
// otherwise use forwarding by calling our `mi_` function
|
// otherwise use forwarding by calling our `mi_` function
|
||||||
#define MI_FORWARD1(fun,x) { return fun(x); }
|
#define MI_FORWARD1(fun,x) { return fun(x); }
|
||||||
#define MI_FORWARD2(fun,x,y) { return fun(x,y); }
|
#define MI_FORWARD2(fun,x,y) { return fun(x,y); }
|
||||||
#define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); }
|
#define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); }
|
||||||
#define MI_FORWARD0(fun,x) { fun(x); }
|
#define MI_FORWARD0(fun,x) { fun(x); }
|
||||||
|
@ -123,10 +123,10 @@ typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t;
|
||||||
// we just override new/delete which does work in a static library.
|
// we just override new/delete which does work in a static library.
|
||||||
#else
|
#else
|
||||||
// On all other systems forward to our API
|
// On all other systems forward to our API
|
||||||
void* malloc(size_t size) MI_FORWARD1(mi_malloc, size)
|
mi_decl_export void* malloc(size_t size) MI_FORWARD1(mi_malloc, size)
|
||||||
void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n)
|
mi_decl_export void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n)
|
||||||
void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize)
|
mi_decl_export void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize)
|
||||||
void free(void* p) MI_FORWARD0(mi_free, p)
|
mi_decl_export void free(void* p) MI_FORWARD0(mi_free, p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__)
|
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__)
|
||||||
|
|
31
src/alloc.c
31
src/alloc.c
|
@ -42,18 +42,20 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
|
||||||
// todo: can we optimize this call away for non-zero'd release mode?
|
// todo: can we optimize this call away for non-zero'd release mode?
|
||||||
#if MI_TRACK_ENABLED
|
#if MI_TRACK_ENABLED
|
||||||
const size_t track_bsize = mi_page_block_size(page);
|
const size_t track_bsize = mi_page_block_size(page);
|
||||||
if (zero) mi_track_mem_defined(block,track_bsize); else mi_track_mem_undefined(block,track_bsize);
|
mi_assert_internal(track_bsize >= size);
|
||||||
|
mi_track_mem_undefined(block,track_bsize - MI_PADDING_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// zero the block? note: we need to zero the full block size (issue #63)
|
// zero the block? note: we need to zero the full block size (issue #63)
|
||||||
if mi_unlikely(zero) {
|
if mi_unlikely(zero) {
|
||||||
mi_assert_internal(page->xblock_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic)
|
mi_assert_internal(page->xblock_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic)
|
||||||
const size_t zsize = (page->is_zero ? sizeof(block->next) : page->xblock_size);
|
const size_t zsize = (page->is_zero ? sizeof(block->next) + MI_PADDING_SIZE : page->xblock_size);
|
||||||
_mi_memzero_aligned(block, zsize);
|
mi_assert(zsize <= track_bsize && zsize >= MI_PADDING_SIZE);
|
||||||
|
_mi_memzero_aligned(block, zsize - MI_PADDING_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (MI_DEBUG>0)
|
#if (MI_DEBUG>0)
|
||||||
if (!page->is_zero && !zero) { memset(block, MI_DEBUG_UNINIT, size); }
|
if (!page->is_zero && !zero) { memset(block, MI_DEBUG_UNINIT, size - MI_PADDING_SIZE); }
|
||||||
#elif (MI_SECURE!=0)
|
#elif (MI_SECURE!=0)
|
||||||
if (!zero) { block->next = 0; } // don't leak internal data
|
if (!zero) { block->next = 0; } // don't leak internal data
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,7 +72,7 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (MI_PADDING > 0) && defined(MI_ENCODE_FREELIST)
|
#if (MI_PADDING > 0) && defined(MI_ENCODE_FREELIST) && !MI_TRACK_ENABLED
|
||||||
mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
|
mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
|
||||||
ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
|
ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
|
||||||
#if (MI_DEBUG>1)
|
#if (MI_DEBUG>1)
|
||||||
|
@ -85,7 +87,10 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mark as no-access again
|
// mark as no-access again
|
||||||
mi_track_mem_noaccess(block,track_bsize);
|
// mi_track_mem_noaccess(block, track_bsize);
|
||||||
|
// mi_track_resize(block,track_bsize,size - MI_PADDING_SIZE);
|
||||||
|
// mi_track_free(block);
|
||||||
|
//mi_track_malloc(block,size - MI_PADDING_SIZE,zero);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +222,7 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
|
||||||
// Check for heap block overflow by setting up padding at the end of the block
|
// Check for heap block overflow by setting up padding at the end of the block
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
#if (MI_PADDING>0) && defined(MI_ENCODE_FREELIST)
|
#if (MI_PADDING>0) && defined(MI_ENCODE_FREELIST) && !MI_TRACK_ENABLED
|
||||||
static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) {
|
static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) {
|
||||||
*bsize = mi_page_usable_block_size(page);
|
*bsize = mi_page_usable_block_size(page);
|
||||||
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
|
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
|
||||||
|
@ -421,7 +426,7 @@ static inline void _mi_free_block(mi_page_t* page, bool local, mi_block_t* block
|
||||||
// owning thread can free a block directly
|
// owning thread can free a block directly
|
||||||
if mi_unlikely(mi_check_is_double_free(page, block)) return;
|
if mi_unlikely(mi_check_is_double_free(page, block)) return;
|
||||||
mi_check_padding(page, block);
|
mi_check_padding(page, block);
|
||||||
#if (MI_DEBUG!=0)
|
#if (MI_DEBUG!=0) && !MI_TRACK_ENABLED
|
||||||
mi_track_mem_undefined(block, mi_page_block_size(page)); // note: check padding may set parts to noaccess
|
mi_track_mem_undefined(block, mi_page_block_size(page)); // note: check padding may set parts to noaccess
|
||||||
memset(block, MI_DEBUG_FREED, mi_page_block_size(page));
|
memset(block, MI_DEBUG_FREED, mi_page_block_size(page));
|
||||||
#endif
|
#endif
|
||||||
|
@ -453,13 +458,11 @@ mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* p
|
||||||
static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) mi_attr_noexcept {
|
static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) mi_attr_noexcept {
|
||||||
mi_page_t* const page = _mi_segment_page_of(segment, p);
|
mi_page_t* const page = _mi_segment_page_of(segment, p);
|
||||||
mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p);
|
mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p);
|
||||||
//#if MI_TRACK_ENABLED
|
const size_t track_bsize = mi_page_block_size(page);
|
||||||
//const size_t track_bsize = mi_page_block_size(page);
|
//mi_track_mem_defined(block,track_bsize);
|
||||||
//#endif
|
|
||||||
//mi_track_mem_defined(block,track_bsize);
|
|
||||||
mi_stat_free(page, block); // stat_free may access the padding
|
mi_stat_free(page, block); // stat_free may access the padding
|
||||||
_mi_free_block(page, local, block);
|
_mi_free_block(page, local, block);
|
||||||
//mi_track_mem_noaccess(block,track_bsize); // use track_bsize as the page may have been deallocated by now
|
//mi_track_mem_noaccess(block,track_bsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the segment data belonging to a pointer
|
// Get the segment data belonging to a pointer
|
||||||
|
|
|
@ -10,13 +10,21 @@
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int* p = mi(malloc)(3*sizeof(int));
|
int* p = mi(malloc)(3*sizeof(int));
|
||||||
int* q = mi(malloc)(sizeof(int));
|
|
||||||
|
|
||||||
int* r = mi_malloc_aligned(8,16);
|
int* r = mi_malloc_aligned(8,16);
|
||||||
mi_free(r);
|
mi_free(r);
|
||||||
|
|
||||||
|
// illegal byte wise read
|
||||||
|
char* c = (char*)mi(malloc)(3);
|
||||||
|
printf("invalid byte: over: %d, under: %d\n", c[4], c[-1]);
|
||||||
|
mi(free)(c);
|
||||||
|
|
||||||
// undefined access
|
// undefined access
|
||||||
|
int* q = mi(malloc)(sizeof(int));
|
||||||
printf("undefined: %d\n", *q);
|
printf("undefined: %d\n", *q);
|
||||||
|
|
||||||
|
// illegal int read
|
||||||
|
printf("invalid: over: %d, under: %d\n", q[1], q[-1]);
|
||||||
|
|
||||||
*q = 42;
|
*q = 42;
|
||||||
|
|
||||||
|
@ -28,6 +36,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
mi(free)(q);
|
mi(free)(q);
|
||||||
|
|
||||||
|
|
||||||
// double free
|
// double free
|
||||||
mi(free)(q);
|
mi(free)(q);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue