diff options
Diffstat (limited to 'contrib/nosefart/memguard.c')
-rw-r--r-- | contrib/nosefart/memguard.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/contrib/nosefart/memguard.c b/contrib/nosefart/memguard.c new file mode 100644 index 000000000..35b3ef6ba --- /dev/null +++ b/contrib/nosefart/memguard.c @@ -0,0 +1,417 @@ +/* +** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) +** +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of version 2 of the GNU Library General +** Public License as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. To obtain a +** copy of the GNU Library General Public License, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Any permitted reproduction of these routines, in whole or in part, +** must bear this legend. +** +** +** memguard.c +** +** memory allocation wrapper routines +** +** NOTE: based on code (c) 1998 the Retrocade group +** $Id: memguard.c,v 1.4 2004/02/20 19:53:39 komadori Exp $ +*/ + +#include "types.h" + +/* undefine macro definitions, so we get real calls */ +#undef malloc +#undef free + +#include <string.h> +#include <stdlib.h> + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif + +#include "memguard.h" +#include "log.h" + + +/* Maximum number of allocated blocks at any one time */ +#define MAX_BLOCKS 16384 + +/* Memory block structure */ +typedef struct memblock_s +{ + void *block_addr; + int block_size; + char *file_name; + int line_num; +} memblock_t; + +boolean mem_debug = TRUE; /* debugging flag */ + + +#ifdef NOFRENDO_DEBUG + +static int mem_blockcount = 0; /* allocated block count */ +static memblock_t *mem_record = NULL; + +#define GUARD_STRING "GgUuAaRrDdSsTtRrIiNnGgBbLlOoCcKk" +#define GUARD_LENGTH 64 /* before and after allocated block */ + + +/* +** Check the memory guard to make sure out of bounds writes have not +** occurred. +*/ +static boolean mem_checkguardblock(void *data, int guard_size) +{ + uint8 *orig, *chk, *blk; + int i, alloc_size; + + /* get the original pointer */ + orig = (((uint8 *) data) - guard_size); + + /* get the size */ + alloc_size = *((uint32 *) orig); + + /* now skip past the size */ + blk = orig + sizeof(uint32); + + /* check leading guard string */ + chk = GUARD_STRING; + for (i = sizeof(uint32); i < guard_size; i++) + { + if (0 == *chk) + chk = GUARD_STRING; + if (*blk != *chk) + return FALSE; + chk++; + blk++; + } + + /* check end of block */ + chk = GUARD_STRING; + blk = ((uint8 *) data) + alloc_size; + for (i = 0; i < guard_size; i++) + { + if (0 == *chk) + chk = GUARD_STRING; + if (*blk != *chk) + return FALSE; + chk++; + blk++; + } + + /* we're okay! */ + return TRUE; +} + +/* free a guard block */ +static void mem_freeguardblock(void *data, int guard_size) +{ + uint8 *orig = (((uint8 *) data) - guard_size); + + free(orig); +} + +/* fill in the memory guard, advance the pointer to the 'real' memory */ +static void *mem_guardblock(int alloc_size, int guard_size) +{ + void *orig; + uint8 *blk, *chk; + int i; + + /* allocate memory */ + orig = calloc(alloc_size + (guard_size * 2), 1); + if (NULL == orig) + return NULL; + + blk = ((uint8 *) orig); + + /* store the size of the newly allocated block*/ + *((uint32 *) blk) = alloc_size; + + /* skip past the size */ + blk += sizeof(uint32); + + /* put guard string at beginning of block */ + chk = GUARD_STRING; + for (i = sizeof(uint32); i < guard_size; i++) + { + if (0 == *chk) + chk = GUARD_STRING; + *blk++ = *chk++; + } + + /* check end of block */ + chk = GUARD_STRING; + blk = guard_size + (uint8 *) orig + alloc_size; + for (i = 0; i < guard_size; i++) + { + if (0 == *chk) + chk = GUARD_STRING; + *blk++ = *chk++; + } + + return (void *) (guard_size + (uint8 *) orig); +} + + +/* Allocate a bunch of memory to keep track of all memory blocks */ +static void mem_init(void) +{ + if (mem_record) + { + free(mem_record); + mem_record = NULL; + } + + mem_record = calloc(MAX_BLOCKS * sizeof(memblock_t), 1); + ASSERT(mem_record); +} + +/* add a block of memory to the master record */ +static void mem_addblock(void *data, int block_size, char *file, int line) +{ + int i; + + for (i = 0; i < MAX_BLOCKS; i++) + { + if (NULL == mem_record[i].block_addr) + { + mem_record[i].block_addr = data; + mem_record[i].block_size = block_size; + mem_record[i].file_name = file; + mem_record[i].line_num = line; + return; + } + } + + ASSERT_MSG("out of memory blocks."); +} + +/* find an entry in the block record and delete it */ +static void mem_deleteblock(void *data, char *file, int line) +{ + int i; + char fail[256]; + + for (i = 0; i < MAX_BLOCKS; i++) + { + if (data == mem_record[i].block_addr) + { + if (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) + { + sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block corrupt", + (uint32) data, line, file); + ASSERT_MSG(fail); + } + + memset(&mem_record[i], 0, sizeof(memblock_t)); + return; + } + } + + sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block not found", + (uint32) data, line, file); + ASSERT_MSG(fail); +} +#endif /* NOFRENDO_DEBUG */ + +/* allocates memory and clears it */ +#ifdef NOFRENDO_DEBUG +void *_my_malloc(int size, char *file, int line) +#else +void *_my_malloc(int size) +#endif +{ + void *temp; + char fail[256]; + +#ifdef NOFRENDO_DEBUG + if (NULL == mem_record && FALSE != mem_debug) + mem_init(); + + if (FALSE != mem_debug) + temp = mem_guardblock(size, GUARD_LENGTH); + else +#endif /* NOFRENDO_DEBUG */ + temp = calloc(sizeof(uint8), size); + + if (NULL == temp) + { +#ifdef NOFRENDO_DEBUG + sprintf(fail, "malloc: out of memory at line %d of %s. block size: %d\n", + line, file, size); +#else + sprintf(fail, "malloc: out of memory. block size: %d\n", size); +#endif + ASSERT_MSG(fail); + } + +#ifdef NOFRENDO_DEBUG + if (FALSE != mem_debug) + mem_addblock(temp, size, file, line); + + mem_blockcount++; +#endif + + return temp; +} + +/* free a pointer allocated with my_malloc */ +#ifdef NOFRENDO_DEBUG +void _my_free(void **data, char *file, int line) +#else +void _my_free(void **data) +#endif +{ + char fail[256]; + + if (NULL == data || NULL == *data + || ((uintptr_t)-1) == (uintptr_t) *data || ((uintptr_t)-1) == (uintptr_t) data) + { +#ifdef NOFRENDO_DEBUG + sprintf(fail, "free: attempted to free NULL pointer at line %d of %s\n", + line, file); +#else + sprintf(fail, "free: attempted to free NULL pointer.\n"); +#endif + ASSERT_MSG(fail); + } + +#ifdef NOFRENDO_DEBUG + /* if this is true, we are in REAL trouble */ + if (0 == mem_blockcount) + { + ASSERT_MSG("free: attempted to free memory when no blocks available"); + } + + if (FALSE != mem_debug) + mem_deleteblock(*data, file, line); + + mem_blockcount--; /* dec our block count */ + + if (FALSE != mem_debug) + mem_freeguardblock(*data, GUARD_LENGTH); + else +#endif /* NOFRENDO_DEBUG */ + free(*data); + + *data = NULL; /* NULL our source */ +} + +/* check for orphaned memory handles */ +void mem_checkleaks(void) +{ +#ifdef NOFRENDO_DEBUG + int i; + + if (FALSE == mem_debug) + return; + + if (mem_blockcount) + { + log_printf("memory leak - %d unfreed block%s\n\n", mem_blockcount, + mem_blockcount == 1 ? "" : "s"); + + for (i = 0; i < MAX_BLOCKS; i++) + { + if (mem_record[i].block_addr) + { + log_printf("addr: 0x%08X, size: %d, line %d of %s%s\n", + (uint32) mem_record[i].block_addr, + mem_record[i].block_size, + mem_record[i].line_num, + mem_record[i].file_name, + (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) + ? " -- block corrupt" : ""); + } + } + } + else + log_printf("no memory leaks\n"); +#endif +} + +void mem_checkblocks(void) +{ +#ifdef NOFRENDO_DEBUG + int i; + + if (FALSE == mem_debug) + return; + + for (i = 0; i < MAX_BLOCKS; i++) + { + if (mem_record[i].block_addr) + { + if (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) + { + log_printf("addr: 0x%08X, size: %d, line %d of %s -- block corrupt\n", + (uint32) mem_record[i].block_addr, + mem_record[i].block_size, + mem_record[i].line_num, + mem_record[i].file_name); + } + } + } +#endif /* NOFRENDO_DEBUG */ +} + +/* +** $Log: memguard.c,v $ +** Revision 1.4 2004/02/20 19:53:39 komadori +** Fixed detection of linux framebuffer support. Included xineutils.h in dsputil_mlib.c and added to diff_to_ffmpeg_cvs.txt. Fixed function prototype in dsputil_mlib.c (should be sent back to ffmpeg-dev at some point). Fixed includes in nosefart. Fixed nested comments and includes in goom. +** +** Revision 1.3 2004/02/19 02:50:25 rockyb +** Mandrake patches from +** http://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/SPECS/xine-lib/ +** via Goetz Waschk who reports: +** +** The amd64 patch (xine-lib-1-rc0a-amd64.patch) sets some conservative +** CFLAGS for amd64, +** +** the lib64 patch (xine-lib-1-rc0a-lib64.patch) replaces hardcoded +** /lib to support the lib64 library dir on amd64, +** +** the directfb patch (xine-lib-1-rc2-no-directfb.patch) adds a +** configure option to disable directfb, +** +** the linuxfb patch (xine-lib-1-rc3a-no-linuxfb.patch) does the same +** for linux framebuffer and +** +** the 64bit fixes patch (xine-lib-1-rc3-64bit-fixes.patch) doesn't +** apply at the moment against the CVS -- demux_ogg.c was not applied. +** it includes some 64 bit pointer and other fixes for 64bit architectures. +** from Gwenole Beauchesne +** +** I haven't tested other than apply and compile. +** +** Revision 1.2 2003/12/05 15:55:01 f1rmb +** cleanup phase II. use xprintf when it's relevant, use xine_xmalloc when it's relevant too. Small other little fix (can't remember). Change few internal function prototype because it xine_t pointer need to be used if some xine's internal sections. NOTE: libdvd{nav,read} is still too noisy, i will take a look to made it quit, without invasive changes. To be continued... +** +** Revision 1.1 2003/01/08 07:04:35 tmmm +** initial import of Nosefart sources +** +** Revision 1.8 2000/06/26 04:54:48 matt +** simplified and made more robust +** +** Revision 1.7 2000/06/12 01:11:41 matt +** cleaned up some error output for win32 +** +** Revision 1.6 2000/06/09 15:12:25 matt +** initial revision +** +*/ |