Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248#include "precomp.h"
#ifdef _DEBUG_MEM
#define REDZONE_SIZE 32#define REDZONE_LEFT 0x78#define REDZONE_RIGHT 0x87
typedef struct{ size_t size; LIST_ENTRY list_entry; const char *file; int line;} alloc_info, *palloc_info;
static size_t allocations = 0;static size_t allocated_memory = 0;static LIST_ENTRY alloc_list_head = {&alloc_list_head, &alloc_list_head};
static void *get_base_ptr(void *ptr){ return (void *)((UINT_PTR)ptr - REDZONE_SIZE - sizeof(alloc_info));}
static void *get_ptr_from_base(palloc_info info){ return (void*)((size_t)(info + 1) + REDZONE_SIZE);}
static void *write_redzone(void *ptr, size_t size, const char *file, int line){ void *ret; palloc_info info = (palloc_info)ptr;
info->size = size; info->file = file; info->line = line;
ptr = (void *)(info + 1); memset(ptr, REDZONE_LEFT, REDZONE_SIZE); ret = (void *)((size_t)ptr + REDZONE_SIZE); ptr = (void *)((size_t)ret + size); memset(ptr, REDZONE_RIGHT, REDZONE_SIZE); return ret;}
static intcheck_redzone_region(void *ptr, unsigned char sig, void **newptr){ unsigned char *p, *q; int ret = 1;
p = (unsigned char *)ptr; q = p + REDZONE_SIZE; while (p != q) { if (*(p++) != sig) ret = 0; }
if (newptr != NULL) *newptr = p; return ret;}
static voidredzone_err(const char *msg, palloc_info info, void *ptr, const char *file, int line){ DbgPrint("CMD: %s\n", msg); DbgPrint(" Block: 0x%p Size: %lu\n", ptr, info->size); DbgPrint(" Allocated from %s:%d\n", info->file, info->line); DbgPrint(" Detected at: %s:%d\n", file, line); ASSERT(FALSE); ExitProcess(1);}
static voidcheck_redzone(void *ptr, const char *file, int line){ palloc_info info = (palloc_info)ptr; ptr = (void *)(info + 1); if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr)) redzone_err("Detected buffer underflow!", info, ptr, file, line); ptr = (void *)((UINT_PTR)ptr + info->size); if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL)) redzone_err("Detected buffer overflow!", info, ptr, file, line);}
static size_tcalculate_size_with_redzone(size_t size){ return sizeof(alloc_info) + size + (2 * REDZONE_SIZE);}
static voidadd_mem_to_list(void *ptr){ palloc_info info = (palloc_info)ptr; InsertTailList(&alloc_list_head, &info->list_entry);}
static voiddel_mem_from_list(void *ptr){ palloc_info info = (palloc_info)ptr; RemoveEntryList(&info->list_entry);}
static voiddump_mem_list(void){ palloc_info info; PLIST_ENTRY entry; void *ptr;
entry = alloc_list_head.Flink; while (entry != &alloc_list_head) { info = CONTAINING_RECORD(entry, alloc_info, list_entry);
DbgPrint(" * Block: 0x%p Size: %lu allocated from %s:%d\n", get_ptr_from_base(info), info->size, info->file, info->line);
ptr = (void *)(info + 1); if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr)) { DbgPrint(" !!! Detected buffer underflow !!!\n"); }
ptr = (void *)((UINT_PTR)ptr + info->size); if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL)) { DbgPrint(" !!! Detected buffer overflow !!!\n"); }
entry = entry->Flink; }}
void *cmd_alloc_dbg(size_t size, const char *file, int line){ void *newptr = NULL;
newptr = malloc(calculate_size_with_redzone(size)); if (newptr != NULL) { allocations++; allocated_memory += size; add_mem_to_list(newptr); newptr = write_redzone(newptr, size, file, line); }
return newptr;}
void *cmd_realloc_dbg(void *ptr, size_t size, const char *file, int line){ size_t prev_size; void *newptr = NULL;
if (ptr == NULL) return cmd_alloc_dbg(size, file, line); if (size == 0) { cmd_free_dbg(ptr, file, line); return NULL; }
ptr = get_base_ptr(ptr); prev_size = ((palloc_info)ptr)->size; check_redzone(ptr, file, line);
del_mem_from_list(ptr); newptr = realloc(ptr, calculate_size_with_redzone(size)); if (newptr != NULL) { allocated_memory += size - prev_size; add_mem_to_list(newptr); newptr = write_redzone(newptr, size, file, line); } else add_mem_to_list(ptr);
return newptr;}
voidcmd_free_dbg(void *ptr, const char *file, int line){ if (ptr != NULL) { ptr = get_base_ptr(ptr); check_redzone(ptr, file, line); allocations--; allocated_memory -= ((palloc_info)ptr)->size; del_mem_from_list(ptr); }
free(ptr);}
TCHAR *cmd_dup_dbg(const TCHAR *str, const char *file, int line){ TCHAR *ptr = NULL;
if (str != NULL) { ptr = (TCHAR *)cmd_alloc_dbg((_tcslen(str) + 1) * sizeof(TCHAR), file, line); if (ptr != NULL) { _tcscpy(ptr, str); } }
return ptr;}
voidcmd_checkbuffer_dbg(void *ptr, const char *file, int line){ if (ptr != NULL) { ptr = get_base_ptr(ptr); check_redzone(ptr, file, line); }}
voidcmd_exit(int code){ if (allocations != 0 || allocated_memory != 0) { DbgPrint("CMD: Leaking %lu bytes of memory in %lu blocks! Exit code: %d\n", allocated_memory, allocations, code); if (allocations != 0) dump_mem_list(); }
ExitProcess(code);}
#endif /* _DEBUG_MEM */