Reactos
at listview 247 lines 5.5 kB view raw
1#include "precomp.h" 2 3#ifdef _DEBUG_MEM 4 5#define REDZONE_SIZE 32 6#define REDZONE_LEFT 0x78 7#define REDZONE_RIGHT 0x87 8 9typedef struct 10{ 11 size_t size; 12 LIST_ENTRY list_entry; 13 const char *file; 14 int line; 15} alloc_info, *palloc_info; 16 17static size_t allocations = 0; 18static size_t allocated_memory = 0; 19static LIST_ENTRY alloc_list_head = {&alloc_list_head, &alloc_list_head}; 20 21static void * 22get_base_ptr(void *ptr) 23{ 24 return (void *)((UINT_PTR)ptr - REDZONE_SIZE - sizeof(alloc_info)); 25} 26 27static void * 28get_ptr_from_base(palloc_info info) 29{ 30 return (void*)((size_t)(info + 1) + REDZONE_SIZE); 31} 32 33static void * 34write_redzone(void *ptr, size_t size, const char *file, int line) 35{ 36 void *ret; 37 palloc_info info = (palloc_info)ptr; 38 39 info->size = size; 40 info->file = file; 41 info->line = line; 42 43 ptr = (void *)(info + 1); 44 memset(ptr, REDZONE_LEFT, REDZONE_SIZE); 45 ret = (void *)((size_t)ptr + REDZONE_SIZE); 46 ptr = (void *)((size_t)ret + size); 47 memset(ptr, REDZONE_RIGHT, REDZONE_SIZE); 48 return ret; 49} 50 51static int 52check_redzone_region(void *ptr, unsigned char sig, void **newptr) 53{ 54 unsigned char *p, *q; 55 int ret = 1; 56 57 p = (unsigned char *)ptr; 58 q = p + REDZONE_SIZE; 59 while (p != q) 60 { 61 if (*(p++) != sig) 62 ret = 0; 63 } 64 65 if (newptr != NULL) 66 *newptr = p; 67 return ret; 68} 69 70static void 71redzone_err(const char *msg, palloc_info info, void *ptr, const char *file, int line) 72{ 73 DbgPrint("CMD: %s\n", msg); 74 DbgPrint(" Block: 0x%p Size: %lu\n", ptr, info->size); 75 DbgPrint(" Allocated from %s:%d\n", info->file, info->line); 76 DbgPrint(" Detected at: %s:%d\n", file, line); 77 ASSERT(FALSE); 78 ExitProcess(1); 79} 80 81static void 82check_redzone(void *ptr, const char *file, int line) 83{ 84 palloc_info info = (palloc_info)ptr; 85 ptr = (void *)(info + 1); 86 if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr)) 87 redzone_err("Detected buffer underflow!", info, ptr, file, line); 88 ptr = (void *)((UINT_PTR)ptr + info->size); 89 if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL)) 90 redzone_err("Detected buffer overflow!", info, ptr, file, line); 91} 92 93static size_t 94calculate_size_with_redzone(size_t size) 95{ 96 return sizeof(alloc_info) + size + (2 * REDZONE_SIZE); 97} 98 99static void 100add_mem_to_list(void *ptr) 101{ 102 palloc_info info = (palloc_info)ptr; 103 InsertTailList(&alloc_list_head, &info->list_entry); 104} 105 106static void 107del_mem_from_list(void *ptr) 108{ 109 palloc_info info = (palloc_info)ptr; 110 RemoveEntryList(&info->list_entry); 111} 112 113static void 114dump_mem_list(void) 115{ 116 palloc_info info; 117 PLIST_ENTRY entry; 118 void *ptr; 119 120 entry = alloc_list_head.Flink; 121 while (entry != &alloc_list_head) 122 { 123 info = CONTAINING_RECORD(entry, alloc_info, list_entry); 124 125 DbgPrint(" * Block: 0x%p Size: %lu allocated from %s:%d\n", get_ptr_from_base(info), info->size, info->file, info->line); 126 127 ptr = (void *)(info + 1); 128 if (!check_redzone_region(ptr, REDZONE_LEFT, &ptr)) 129 { 130 DbgPrint(" !!! Detected buffer underflow !!!\n"); 131 } 132 133 ptr = (void *)((UINT_PTR)ptr + info->size); 134 if (!check_redzone_region(ptr, REDZONE_RIGHT, NULL)) 135 { 136 DbgPrint(" !!! Detected buffer overflow !!!\n"); 137 } 138 139 entry = entry->Flink; 140 } 141} 142 143void * 144cmd_alloc_dbg(size_t size, const char *file, int line) 145{ 146 void *newptr = NULL; 147 148 newptr = malloc(calculate_size_with_redzone(size)); 149 if (newptr != NULL) 150 { 151 allocations++; 152 allocated_memory += size; 153 add_mem_to_list(newptr); 154 newptr = write_redzone(newptr, size, file, line); 155 } 156 157 return newptr; 158} 159 160void * 161cmd_realloc_dbg(void *ptr, size_t size, const char *file, int line) 162{ 163 size_t prev_size; 164 void *newptr = NULL; 165 166 if (ptr == NULL) 167 return cmd_alloc_dbg(size, file, line); 168 if (size == 0) 169 { 170 cmd_free_dbg(ptr, file, line); 171 return NULL; 172 } 173 174 ptr = get_base_ptr(ptr); 175 prev_size = ((palloc_info)ptr)->size; 176 check_redzone(ptr, file, line); 177 178 del_mem_from_list(ptr); 179 newptr = realloc(ptr, calculate_size_with_redzone(size)); 180 if (newptr != NULL) 181 { 182 allocated_memory += size - prev_size; 183 add_mem_to_list(newptr); 184 newptr = write_redzone(newptr, size, file, line); 185 } 186 else 187 add_mem_to_list(ptr); 188 189 return newptr; 190} 191 192void 193cmd_free_dbg(void *ptr, const char *file, int line) 194{ 195 if (ptr != NULL) 196 { 197 ptr = get_base_ptr(ptr); 198 check_redzone(ptr, file, line); 199 allocations--; 200 allocated_memory -= ((palloc_info)ptr)->size; 201 del_mem_from_list(ptr); 202 } 203 204 free(ptr); 205} 206 207TCHAR * 208cmd_dup_dbg(const TCHAR *str, const char *file, int line) 209{ 210 TCHAR *ptr = NULL; 211 212 if (str != NULL) 213 { 214 ptr = (TCHAR *)cmd_alloc_dbg((_tcslen(str) + 1) * sizeof(TCHAR), file, line); 215 if (ptr != NULL) 216 { 217 _tcscpy(ptr, str); 218 } 219 } 220 221 return ptr; 222} 223 224void 225cmd_checkbuffer_dbg(void *ptr, const char *file, int line) 226{ 227 if (ptr != NULL) 228 { 229 ptr = get_base_ptr(ptr); 230 check_redzone(ptr, file, line); 231 } 232} 233 234void 235cmd_exit(int code) 236{ 237 if (allocations != 0 || allocated_memory != 0) 238 { 239 DbgPrint("CMD: Leaking %lu bytes of memory in %lu blocks! Exit code: %d\n", allocated_memory, allocations, code); 240 if (allocations != 0) 241 dump_mem_list(); 242 } 243 244 ExitProcess(code); 245} 246 247#endif /* _DEBUG_MEM */