From 49ad301d3d38789f5715bcbfa986bec35ccf2d14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Nov 2012 20:03:21 +0900 Subject: [PATCH] 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. --- include/QF/zone.h | 2 +- libs/gamecode/pr_exec.c | 5 +++++ libs/util/zone.c | 26 +++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index fa94071a6..22c7bc19f 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -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); diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 70b5a044a..0158bc5ef 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -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 diff --git a/libs/util/zone.c b/libs/util/zone.c index e83e50191..6290b1445 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -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 {