void * _xmalloc(unsigned size, const char *filen, int line) { uint32_t *data; void *p; chk_header *ch; p = (void*) malloc (size + sizeof(chk_header) + MAGIC_MEMORY_SIZE); ASSERT(p != NULL); ASSERT(filen != NULL); /* Fix block header */ ch = (chk_header*)p; ch->key = tick++; ch->size = size; ch->magic = MAGIC_MEMORY; data = (uint32_t*)((chk_header *)p + 1); #if 0 memset((void*)data, 0xf0, size); #else memset((void*)data, 0, size); #endif /* Fix block tail */ memcpy(((uint8_t*)data) + size, &ch->magic, MAGIC_MEMORY_SIZE); /* Check set up okay */ if (chk_header_okay(ch) == FALSE) { fprintf(stderr, "Implementation Error\n"); abort(); } /* Add table entry */ mem_item[naddr].key = ch->key; mem_item[naddr].addr = p; mem_item[naddr].filen = (char *)strdup(filen); mem_item[naddr].line = line; mem_item[naddr].length = strlen(filen); mem_item[naddr].blen = 0; /* block_alloc'ed len when appropriate */ mem_item[naddr].est = ch->key; /* changes when block_alloc recycles block */ naddr ++; if (naddr >= MAX_ADDRS) { fprintf(stderr, "ERROR: Allocated too much! Table overflow in xmalloc()\n"); fprintf(stderr, " Do you really need to allocate more than %d items?\n", MAX_ADDRS); abort(); } if (chk_header_okay(ch) == FALSE) { fprintf(stderr, "Implementation Error\n"); abort(); } printf("malloc at %p\n", p); return (uint8_t*)p + sizeof(chk_header); }
/** * xclaim: * @addr: address * @filen: new filename * @line: new allocation line * * Coerces information in allocation table about allocation file and * line to be @filen and @line. This is used by the evil * block_alloc() and should probably not be used anywhere else ever. **/ void xclaim(void *addr, const char *filen, int line) { alloc_blk *m; chk_header *ch; ch = ((chk_header *)addr) - 1; m = mem_item_find(ch->key); if (chk_header_okay(ch) == FALSE) { fprintf(stderr, "xclaim: memory corrupted\n"); abort(); } if (m == NULL) { fprintf(stderr, "xclaim: block not found\n"); abort(); } free(m->filen); m->filen = strdup(filen); m->length = strlen(filen); m->line = line; m->est = tick++; }
/** * xfree: * @p: pointer to block to freed. * * Free block of memory. Semantically equivalent to free(), but * checks for bounds overruns in @p and tidies up state associated * additional functionality. * * Must be used to free memory allocated with xmalloc(), xrealloc(), * and xstrdup(). **/ void xfree(void *p) { alloc_blk *m; chk_header *ch; uint32_t size, delta, magic, idx; if (p == NULL) { printf("ERROR: Attempt to free NULL pointer!\n"); abort(); } ch = ((chk_header*)p) - 1; printf("free at %p\n", ch); /* Validate entry */ if (chk_header_okay(ch) == FALSE) { printf("ERROR: Freeing corrupted block\n"); abort(); } /* Locate in table */ m = mem_item_find(ch->key); if (m == NULL) { printf("ERROR: Freeing unallocated or already free'd block\n"); abort(); } /* Trash memory of allocated block, maybe noticed by apps when * deref'ing free'd */ size = ch->size + sizeof(chk_header) + MAGIC_MEMORY_SIZE; magic = MAGIC_MEMORY; p = (uint8_t*)ch; while (size > 0) { delta = min(size, 4); memcpy(p, &magic, delta); (uint8_t*)p += delta; size -= delta; } /* Free memory */ free(ch); free(m->filen); /* Remove from table */ idx = m - mem_item; if (naddr - idx > 0) { memmove(&mem_item[idx], &mem_item[idx + 1], (naddr - idx - 1) * sizeof(alloc_blk)); } naddr--; xmemchk(); }
/** * xmemchk: * @void: * * Check for bounds overruns in all memory allocated with xmalloc(), * xrealloc(), and xstrdup(). Information on corrupted blocks is * rendered on the standard error stream. This includes where the * block was allocated, the size of the block, and the number of * allocations made since the block was created. **/ void xmemchk(void) { uint32_t last_key; chk_header *ch; int i; if (naddr > MAX_ADDRS) { fprintf(stderr, "ERROR: Too many addresses for xmemchk()!\n"); abort(); } last_key = 0; for (i = 0; i < naddr; i++) { /* Check for table corruption */ if (mem_item[i].key < last_key) { fprintf(stderr, "Memory table keys out of order - fatal error"); abort(); } last_key = mem_item[i].key; if (mem_item[i].addr == NULL) { fprintf(stderr, "Memory table entry reference null block - fatal error"); abort(); } if (mem_item[i].filen == NULL) { fprintf(stderr, "Memory table filename missing - fatal error"); abort(); } if ((size_t) strlen(mem_item[i].filen) != mem_item[i].length) { fprintf(stderr, "Memory table filename length corrupted - fatal error"); abort(); } /* Check memory */ ch = mem_item[i].addr; if (chk_header_okay(ch) == FALSE) { /* Chk header display which side has gone awry */ fprintf(stderr, "Memory check failed!\n"); fprintf(stderr, "addr: %p", mem_item[i].addr); fprintf(stderr, " size: %6d", ch->size); fprintf(stderr, " age: %6d", tick - mem_item[i].est); fprintf(stderr, " file: %s", mem_item[i].filen); fprintf(stderr, " line: %d", mem_item[i].line); fprintf(stderr, "\n"); abort(); } } }
void * _xrealloc(void *p, unsigned size, const char *filen, int line) { alloc_blk *m; chk_header *ch; uint8_t *t; assert(p != NULL); assert(filen != NULL); ch = ((chk_header*) p) - 1; m = mem_item_find(ch->key); if (m != NULL) { /* Attempt reallocation */ m->addr = realloc((void*)ch, size + sizeof(chk_header) + MAGIC_MEMORY_SIZE); if (m->addr == NULL) { debug_msg("realloc failed\n"); return NULL; } /* update ch/p */ ch = (chk_header*)m->addr; p = (void*)(ch+1); /* Update table */ free(m->filen); m->filen = (char *) strdup(filen); m->line = line; m->length = strlen(filen); m->est = tick++; /* Fix chunk header */ ch->size = size; /* Fix trailer */ t = (uint8_t*)p + size; memcpy(t, &ch->magic, MAGIC_MEMORY_SIZE); /* Check block is okay */ if (chk_header_okay(ch) == FALSE) { fprintf(stderr, "Implementation Error\n"); abort(); } return p; } debug_msg("Trying to xrealloc() memory not which is not allocated\n"); abort(); return 0; }