Add improved memory checking to progs.

With pr_boundscheck >= 2, pointer access will be checked against allocated
blocks (qfvalgrind?:). Currently extremely basic, but it seems to work.
This commit is contained in:
Bill Currie 2012-11-19 20:03:21 +09:00
parent 56103f9a38
commit 49ad301d3d
3 changed files with 31 additions and 2 deletions

View file

@ -103,7 +103,7 @@ void Z_Print (memzone_t *zone);
void Z_CheckHeap (memzone_t *zone);
void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg),
void *data);
void Z_CheckPointer (const memzone_t *zone, const void *ptr, int size);
void *Hunk_Alloc (int size); // returns 0 filled memory
void *Hunk_AllocName (int size, const char *name);

View file

@ -261,6 +261,11 @@ PR_BoundsCheckSize (progs_t *pr, int addr, unsigned size)
|| size > (unsigned) (pr->globals_size - addr))
PR_RunError (pr, "invalid memory access: %d (0 to %d-%d)", addr,
pr->globals_size, size);
if (pr_boundscheck->int_val >= 2
&& PR_GetPointer (pr, addr + size) > (pr_type_t *) pr->zone) {
void *mem = (void *) PR_GetPointer (pr, addr);
Z_CheckPointer (pr->zone, mem, size * sizeof (pr_type_t));
}
}
VISIBLE void

View file

@ -363,7 +363,7 @@ Z_CheckHeap (memzone_t *zone)
if ( (byte *)block + block->size != (byte *)block->next)
Sys_Error ("Z_CheckHeap: block size does not touch the next "
"block\n");
if ( block->next->prev != block)
if (block->next->prev != block)
Sys_Error ("Z_CheckHeap: next block doesn't have proper back "
"link\n");
if (!block->tag && !block->next->tag)
@ -378,6 +378,30 @@ Z_SetError (memzone_t *zone, void (*err) (void *, const char *), void *data)
zone->data = data;
}
void
Z_CheckPointer (const memzone_t *zone, const void *ptr, int size)
{
const memblock_t *block;
const char *block_mem;
const char *check = (char *) ptr;
for (block = zone->blocklist.next ; ; block = block->next) {
if (block->next == &zone->blocklist)
break; // all blocks have been hit
if (check < (const char *) block
|| check >= (const char *) block + block->size)
continue;
// a block that overlaps with the memory region has been found
if (!block->tag)
zone->error (zone->data, "invalid access to unallocated memory");
block_mem = (char *) &block[1];
if (check < block_mem
|| check + size > block_mem + block->size - sizeof (*block))
zone->error (zone->data, "invalid access to allocated memory");
return; // access ok
}
}
//============================================================================
typedef struct {