Report the correct and wrong sizes on sized dealloc bug detection.

This commit is contained in:
Qi Wang 2021-02-05 17:26:45 -08:00 committed by Qi Wang
parent f3b2668b32
commit 041145c272
5 changed files with 30 additions and 16 deletions

View File

@ -228,9 +228,10 @@ large_dalloc_safety_checks(edata_t *edata, void *ptr, szind_t szind) {
(uintptr_t)edata_addr_get(edata)); (uintptr_t)edata_addr_get(edata));
return true; return true;
} }
if (unlikely(sz_index2size(szind) != edata_usize_get(edata))) { size_t input_size = sz_index2size(szind);
safety_check_fail_sized_dealloc(/* current_dealloc */ true, if (unlikely(input_size != edata_usize_get(edata))) {
ptr); safety_check_fail_sized_dealloc(/* current_dealloc */ true, ptr,
/* true_size */ edata_usize_get(edata), input_size);
return true; return true;
} }

View File

@ -1,7 +1,8 @@
#ifndef JEMALLOC_INTERNAL_SAFETY_CHECK_H #ifndef JEMALLOC_INTERNAL_SAFETY_CHECK_H
#define JEMALLOC_INTERNAL_SAFETY_CHECK_H #define JEMALLOC_INTERNAL_SAFETY_CHECK_H
void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr); void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr,
size_t true_size, size_t input_size);
void safety_check_fail(const char *format, ...); void safety_check_fail(const char *format, ...);
/* Can set to NULL for a default. */ /* Can set to NULL for a default. */
void safety_check_set_abort(void (*abort_fn)(const char *)); void safety_check_set_abort(void (*abort_fn)(const char *));

View File

@ -2751,7 +2751,9 @@ maybe_check_alloc_ctx(tsd_t *tsd, void *ptr, emap_alloc_ctx_t *alloc_ctx) {
&dbg_ctx); &dbg_ctx);
if (alloc_ctx->szind != dbg_ctx.szind) { if (alloc_ctx->szind != dbg_ctx.szind) {
safety_check_fail_sized_dealloc( safety_check_fail_sized_dealloc(
/* current_dealloc */ true, ptr); /* current_dealloc */ true, ptr,
/* true_size */ sz_size2index(dbg_ctx.szind),
/* input_size */ sz_size2index(alloc_ctx->szind));
return true; return true;
} }
if (alloc_ctx->slab != dbg_ctx.slab) { if (alloc_ctx->slab != dbg_ctx.slab) {
@ -2800,9 +2802,13 @@ isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) {
if (config_opt_safety_checks) { if (config_opt_safety_checks) {
/* Small alloc may have !slab (sampled). */ /* Small alloc may have !slab (sampled). */
if (alloc_ctx.szind != sz_size2index(usize)) { if (unlikely(alloc_ctx.szind !=
safety_check_fail_sized_dealloc(true, sz_size2index(usize))) {
ptr); safety_check_fail_sized_dealloc(
/* current_dealloc */ true, ptr,
/* true_size */ sz_index2size(
alloc_ctx.szind),
/* input_size */ usize);
} }
} }
} else { } else {

View File

@ -3,14 +3,16 @@
static void (*safety_check_abort)(const char *message); static void (*safety_check_abort)(const char *message);
void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr) { void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr,
size_t true_size, size_t input_size) {
char *src = current_dealloc ? "the current pointer being freed" : char *src = current_dealloc ? "the current pointer being freed" :
"in thread cache, possibly from previous deallocations"; "in thread cache, possibly from previous deallocations";
safety_check_fail("<jemalloc>: size mismatch detected, likely caused by" safety_check_fail("<jemalloc>: size mismatch detected (true size %zu "
" application sized deallocation bugs (source address: %p, %s). " "vs input size %zu), likely caused by application sized "
"Suggest building with --enable-debug or address sanitizer for " "dealloction bugs (source address: %p, %s). Suggest building with "
"debugging. Abort.\n", ptr, src); "--enable-debug or address sanitizer for debugging. Abort.\n",
true_size, input_size, ptr, src);
} }
void safety_check_set_abort(void (*abort_fn)(const char *)) { void safety_check_set_abort(void (*abort_fn)(const char *)) {

View File

@ -255,10 +255,14 @@ tcache_bin_flush_size_check_fail(cache_bin_ptr_array_t *arr, szind_t szind,
size_t nptrs, emap_batch_lookup_result_t *edatas) { size_t nptrs, emap_batch_lookup_result_t *edatas) {
bool found_mismatch = false; bool found_mismatch = false;
for (size_t i = 0; i < nptrs; i++) { for (size_t i = 0; i < nptrs; i++) {
if (edata_szind_get(edatas[i].edata) != szind) { szind_t true_szind = edata_szind_get(edatas[i].edata);
if (true_szind != szind) {
found_mismatch = true; found_mismatch = true;
safety_check_fail_sized_dealloc(false, safety_check_fail_sized_dealloc(
tcache_bin_flush_ptr_getter(arr, i)); /* current_dealloc */ false,
/* ptr */ tcache_bin_flush_ptr_getter(arr, i),
/* true_size */ sz_index2size(true_szind),
/* input_size */ sz_index2size(szind));
} }
} }
assert(found_mismatch); assert(found_mismatch);