mirror of
https://github.com/microsoft/mimalloc.git
synced 2024-12-27 13:33:18 +08:00
add corrupted block scanning on overflow detection
This commit is contained in:
parent
083392fa15
commit
8a7d5804bc
39
src/alloc.c
39
src/alloc.c
@ -202,6 +202,8 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST)
|
||||
static void mi_check_padding(const mi_page_t* page, const mi_block_t* block);
|
||||
|
||||
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);
|
||||
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
|
||||
@ -242,9 +244,40 @@ static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
|
||||
size_t size;
|
||||
size_t wrong;
|
||||
if (!mi_verify_padding(page,block,&size,&wrong)) {
|
||||
char msg[80];
|
||||
snprintf(msg, 79, "buffer overflow in heap block (write after %zu bytes)", (wrong > 0 ? wrong - 1 : wrong));
|
||||
_mi_page_block_error_message(EFAULT, page, block, msg );
|
||||
char msg[128];
|
||||
snprintf(msg, 127, "buffer overflow in heap block (write after > %zu bytes), at", wrong);
|
||||
_mi_page_block_error_message(0, page, block, msg );
|
||||
// Get page info
|
||||
const mi_segment_t* segment = _mi_page_segment(page);
|
||||
size_t psize;
|
||||
const mi_block_t* first = (mi_block_t*)_mi_page_start(segment, page, &psize);
|
||||
const size_t bsize = mi_page_block_size(page); // full block size including padding
|
||||
const mi_block_t* last = (mi_block_t*)((uint8_t*)first + (bsize*page->capacity));
|
||||
#define MI_BLOCK_REL(blk,n) ((mi_block_t*)((uint8_t*)(blk) + ((n)*bsize)))
|
||||
// search down from this block to the first one that is not corrupted
|
||||
const mi_block_t* low;
|
||||
size_t size2;
|
||||
size_t wrong2;
|
||||
for (low = MI_BLOCK_REL(block, -1); low >= first; low = MI_BLOCK_REL(low, -1)) {
|
||||
if (mi_verify_padding(page, low, &size2, &wrong2)) break;
|
||||
}
|
||||
if (low < MI_BLOCK_REL(block,-1)) {
|
||||
snprintf(msg, 127, "the overflow may have originated earlier (write after > %zu bytes), from", wrong + (((uint8_t*)block - (uint8_t*)low)) - bsize);
|
||||
_mi_page_block_error_message(0, page, low, msg);
|
||||
}
|
||||
else {
|
||||
low = MI_BLOCK_REL(block,-1);
|
||||
}
|
||||
// search upward to last uncorrupted block
|
||||
const mi_block_t* hi;
|
||||
for (hi = MI_BLOCK_REL(block,1); hi < last; hi = MI_BLOCK_REL(hi, 1)) {
|
||||
if (mi_verify_padding(page, hi, &size, &wrong)) break;
|
||||
}
|
||||
if (hi > (MI_BLOCK_REL(block, 1))) {
|
||||
snprintf(msg, 127, "the overflow may have spanned further (write after > %zu bytes), upto", ((uint8_t*)hi - (uint8_t*)low) - bsize);
|
||||
_mi_page_block_error_message(0, page, hi, msg);
|
||||
}
|
||||
_mi_error_message(EFAULT,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,6 +363,7 @@ void mi_register_error(mi_error_fun* fun, void* arg) {
|
||||
}
|
||||
|
||||
static void mi_call_error_handler(int err) {
|
||||
if (err == 0) return;
|
||||
if (mi_error_handler != NULL) {
|
||||
mi_error_handler(err, mi_atomic_read_ptr(void, &mi_error_arg));
|
||||
}
|
||||
@ -372,11 +373,13 @@ static void mi_call_error_handler(int err) {
|
||||
}
|
||||
|
||||
void _mi_error_message(int err, const char* fmt, ...) {
|
||||
// show detailed error message
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
mi_vshow_error_message(fmt, args);
|
||||
va_end(args);
|
||||
if (fmt != NULL) {
|
||||
// show detailed error message
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
mi_vshow_error_message(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
// and call the error handler which may abort (or return normally)
|
||||
mi_call_error_handler(err);
|
||||
}
|
||||
@ -436,20 +439,20 @@ void _mi_page_block_error_message(int err, const mi_page_t* page, const mi_block
|
||||
void* return_addr = mi_source_unpack(padding->source, &fname, &lineno);
|
||||
if (return_addr != NULL) {
|
||||
#ifdef _MSC_VER
|
||||
const char* hint = " hint: paste the code address in the disassembly window in the debugger to find the source location.\n";
|
||||
const char* hint = " hint: paste the 'allocated at' address in the disassembly window in the debugger to find the source location.\n";
|
||||
#else
|
||||
const char* hint = "";
|
||||
#endif
|
||||
mi_show_error_message("%s: at block %p of size %zu allocated at 0x%p.\n%s", msg, block, size, return_addr, hint);
|
||||
mi_show_error_message("%s: block %p of size %zu allocated at 0x%p.\n%s", msg, block, size, return_addr, hint);
|
||||
}
|
||||
else if (fname != NULL) {
|
||||
mi_show_error_message("%s: at block %p of size %zu allocated at %s:%i.\n", msg, block, size, fname, lineno);
|
||||
mi_show_error_message("%s: block %p of size %zu allocated at %s:%i.\n", msg, block, size, fname, lineno);
|
||||
}
|
||||
else {
|
||||
mi_show_error_message("%s: at block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page));
|
||||
mi_show_error_message("%s: block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page));
|
||||
}
|
||||
#else
|
||||
mi_show_error_message("%s: at block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page));
|
||||
mi_show_error_message("%s: block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page));
|
||||
#endif
|
||||
mi_call_error_handler(err);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ static void double_free1();
|
||||
static void double_free2();
|
||||
static void corrupt_free();
|
||||
static void block_overflow1();
|
||||
static void block_overflow2();
|
||||
static void dangling_ptr_write();
|
||||
|
||||
int main() {
|
||||
@ -20,7 +21,8 @@ int main() {
|
||||
// double_free1();
|
||||
// double_free2();
|
||||
// corrupt_free();
|
||||
block_overflow1();
|
||||
// block_overflow1();
|
||||
block_overflow2();
|
||||
// dangling_ptr_write();
|
||||
|
||||
void* p1 = malloc(78);
|
||||
@ -51,6 +53,21 @@ static void block_overflow1() {
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void block_overflow2() {
|
||||
void* p[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
p[i] = mi_malloc(17);
|
||||
}
|
||||
memset(p[10], 0, 90);
|
||||
memset(p[40], 0, 90);
|
||||
memset(p[79], 0, 70);
|
||||
for (int i = 99; i >= 0; i-=2) {
|
||||
if (i > 0) free(p[i - 1]);
|
||||
free(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dangling_ptr_write() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
uint8_t* p = (uint8_t*)mi_malloc(16);
|
||||
|
Loading…
x
Reference in New Issue
Block a user