*/
#include "common.h"
+#include "log.h"
#undef malloc
#undef free
-/* cookies for anybody who recognizes these bytes without help :) */
#define ALLOC_MAGIC 0x1acf
#define FREE_MAGIC 0xfc1d
+const char redzone[] = { '\x03', '\x47', '\x76', '\xc7' };
struct alloc_header {
unsigned int file_id : 8;
static char file_id_map[256][32];
static unsigned int file_ids_used;
+unsigned long alloc_count, alloc_size;
static int
file_id_cmp(const void *a_, const void *b_)
{
struct alloc_header *block;
- block = malloc(sizeof(*block) + size);
+ block = malloc(sizeof(*block) + size + sizeof(redzone));
assert(block != NULL);
+ if (block->magic == ALLOC_MAGIC && block->file_id < file_ids_used) {
+ /* Only report the error, due to possible false positives. */
+ log_module(MAIN_LOG, LOG_WARNING, "Detected possible reallocation: %p (called by %s:%u/%lu; allocated by %u:%u/%u).",
+ block, file, line, (unsigned long)size,
+ block->file_id, block->line, block->size);
+ }
memset(block, 0, sizeof(*block) + size);
+ memcpy((char*)(block + 1) + size, redzone, sizeof(redzone));
block->file_id = get_file_id(file);
block->line = line;
block->size = size;
block->magic = ALLOC_MAGIC;
+ alloc_count++;
+ alloc_size += size;
return block + 1;
}
void *
srvx_realloc(const char *file, unsigned int line, void *ptr, size_t size)
{
- struct alloc_header *block = NULL, *newblock;
+ struct alloc_header *block, *newblock;
- if (ptr) {
- block = (struct alloc_header *)ptr - 1;
- assert(block->magic == ALLOC_MAGIC);
- if (block->size >= size)
- return block + 1;
- }
+ if (!ptr)
+ return srvx_malloc(file, line, size);
- newblock = malloc(sizeof(*newblock) + size);
+ verify(ptr);
+ block = (struct alloc_header *)ptr - 1;
+
+ if (block->size >= size)
+ return block + 1;
+
+ newblock = malloc(sizeof(*newblock) + size + sizeof(redzone));
assert(newblock != NULL);
- memset(newblock, 0, sizeof(*newblock) + size);
+ memset(newblock, 0, sizeof(*newblock));
+ memcpy(newblock + 1, block + 1, block->size);
+ memset((char*)(newblock + 1) + block->size, 0, size - block->size);
+ memcpy((char*)(newblock + 1) + size, redzone, sizeof(redzone));
newblock->file_id = get_file_id(file);
newblock->line = line;
newblock->size = size;
newblock->magic = ALLOC_MAGIC;
+ alloc_count++;
+ alloc_size += size;
- if (ptr) {
- memcpy(newblock + 1, block + 1, block->size);
- size = block->size + sizeof(*block);
- memset(block, 0, size);
- block->magic = FREE_MAGIC;
- free(block);
- }
+ srvx_free(file, line, block + 1);
return newblock + 1;
}
}
void
-srvx_free(const char *file, unsigned int line, void *ptr)
+srvx_free(UNUSED_ARG(const char *file), UNUSED_ARG(unsigned int line), void *ptr)
{
struct alloc_header *block;
size_t size;
if (!ptr)
return;
+ verify(ptr);
block = (struct alloc_header *)ptr - 1;
- assert(block->magic == ALLOC_MAGIC);
- size = block->size + sizeof(*block);
- memset(block, 0, size);
+ size = block->size;
+ memset(block + 1, 0xde, size);
block->magic = FREE_MAGIC;
free(block);
- (void)file; (void)line;
+ alloc_count--;
+ alloc_size -= size;
+}
+
+void
+verify(const void *ptr)
+{
+ const struct alloc_header *header;
+ if (!ptr)
+ return;
+ header = (const struct alloc_header*)ptr - 1;
+ assert(header->magic == ALLOC_MAGIC);
+ assert(!memcmp((char*)(header + 1) + header->size, redzone, sizeof(redzone)));
}