diff options
Diffstat (limited to 'util/memory.c')
-rw-r--r-- | util/memory.c | 651 |
1 files changed, 0 insertions, 651 deletions
diff --git a/util/memory.c b/util/memory.c deleted file mode 100644 index fba760f04..000000000 --- a/util/memory.c +++ /dev/null @@ -1,651 +0,0 @@ -/* memory.c - memory allocation - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * We use our own memory allocation functions instead of plain malloc(), - * so that we can provide some special enhancements: - * a) functions to provide memory from a secure memory. - * b) by looking at the requested allocation size we - * can reuse memory very quickly (e.g. MPI storage) - * (really needed?) - * c) memory usage reporting if compiled with M_DEBUG - * d) memory checking if compiled with M_GUARD - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> - -#include "types.h" -#include "memory.h" -#include "util.h" - -/* FXIME: ugly hack. Need a prototype here but can't include g10lib.h */ -int g10_private_is_secure( const void *p ); - - -#define MAGIC_NOR_BYTE 0x55 -#define MAGIC_SEC_BYTE 0xcc -#define MAGIC_END_BYTE 0xaa - -#if SIZEOF_UNSIGNED_LONG == 8 - #define EXTRA_ALIGN 4 -#else - #define EXTRA_ALIGN 0 -#endif - -#if defined(M_DEBUG) || defined(M_GUARD) - static void membug( const char *fmt, ... ); -#endif - -#ifdef M_DEBUG - - #ifndef M_GUARD - #define M_GUARD 1 - #endif - #undef m_alloc - #undef m_alloc_clear - #undef m_alloc_secure - #undef m_alloc_secure_clear - #undef m_realloc - #undef m_free - #undef m_check - #undef m_strdup - #define FNAME(a) m_debug_ ##a - #define FNAMEPRT , const char *info - #define FNAMEARG , info - #define store_len(p,n,m) do { add_entry(p,n,m, \ - info, __FUNCTION__); } while(0) -#else - #define FNAME(a) m_ ##a - #define FNAMEPRT - #define FNAMEARG - #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \ - ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \ - ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \ - ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \ - : MAGIC_NOR_BYTE; \ - } while(0) -#endif - - -#ifdef M_GUARD -static long used_memory; -#endif - -#ifdef M_DEBUG /* stuff used for memory debuging */ - -struct info_entry { - struct info_entry *next; - unsigned count; /* call count */ - const char *info; /* the reference to the info string */ -}; - -struct memtbl_entry { - const void *user_p; /* for reference: the pointer given to the user */ - size_t user_n; /* length requested by the user */ - struct memtbl_entry *next; /* to build a list of unused entries */ - const struct info_entry *info; /* points into the table with */ - /* the info strings */ - unsigned inuse:1; /* this entry is in use */ - unsigned count:31; -}; - - -#define INFO_BUCKETS 53 -#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS ) -static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */ - -static struct memtbl_entry *memtbl; /* the table with the memory info */ -static unsigned memtbl_size; /* number of allocated entries */ -static unsigned memtbl_len; /* number of used entries */ -static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */ - -static void dump_table_at_exit(void); -static void dump_table(void); -static void check_allmem( const char *info ); - -/**************** - * Put the new P into the debug table and return a pointer to the table entry. - * mode is true for security. BY is the name of the function which called us. - */ -static void -add_entry( byte *p, unsigned n, int mode, const char *info, const char *by ) -{ - unsigned index; - struct memtbl_entry *e; - struct info_entry *ie; - - if( memtbl_len < memtbl_size ) - index = memtbl_len++; - else { - struct memtbl_entry *e; - /* look for a used entry in the table. We take the first one, - * so that freed entries remain as long as possible in the table - * (free appends a new one) - */ - if( (e = memtbl_unused) ) { - index = e - memtbl; - memtbl_unused = e->next; - e->next = NULL; - } - else { /* no free entries in the table: extend the table */ - if( !memtbl_size ) { /* first time */ - memtbl_size = 100; - if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) ) - membug("memory debug table malloc failed\n"); - index = 0; - memtbl_len = 1; - atexit( dump_table_at_exit ); - } - else { /* realloc */ - unsigned n = memtbl_size / 4; /* enlarge by 25% */ - if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl))) - membug("memory debug table realloc failed\n"); - memset(memtbl+memtbl_size, 0, n*sizeof *memtbl ); - memtbl_size += n; - index = memtbl_len++; - } - } - } - e = memtbl+index; - if( e->inuse ) - membug("Ooops: entry %u is flagged as in use\n", index); - e->user_p = p + 4; - e->user_n = n; - e->count++; - if( e->next ) - membug("Ooops: entry is in free entry list\n"); - /* do we already have this info string */ - for( ie = info_strings[info_hash(info)]; ie; ie = ie->next ) - if( ie->info == info ) - break; - if( !ie ) { /* no: make a new entry */ - if( !(ie = malloc( sizeof *ie )) ) - membug("can't allocate info entry\n"); - ie->next = info_strings[info_hash(info)]; - info_strings[info_hash(info)] = ie; - ie->info = info; - ie->count = 0; - } - ie->count++; - e->info = ie; - e->inuse = 1; - - /* put the index at the start of the memory */ - p[0] = index; - p[1] = index >> 8 ; - p[2] = index >> 16 ; - p[3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ; - if( DBG_MEMORY ) - log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by ); -} - - - -/**************** - * Check that the memory block is correct. The magic byte has already been - * checked. Checks which are done here: - * - see whether the index points into our memory table - * - see whether P is the same as the one stored in the table - * - see whether we have already freed this block. - */ -struct memtbl_entry * -check_mem( const byte *p, const char *info ) -{ - unsigned n; - struct memtbl_entry *e; - - n = p[EXTRA_ALIGN+0]; - n |= p[EXTRA_ALIGN+1] << 8; - n |= p[EXTRA_ALIGN+2] << 16; - - if( n >= memtbl_len ) - membug("memory at %p corrupted: index=%u table_len=%u (%s)\n", - p+EXTRA_ALIGN+4, n, memtbl_len, info ); - e = memtbl+n; - - if( e->user_p != p+EXTRA_ALIGN+4 ) - membug("memory at %p corrupted: reference mismatch (%s)\n", - p+EXTRA_ALIGN+4, info ); - if( !e->inuse ) - membug("memory at %p corrupted: marked as free (%s)\n", - p+EXTRA_ALIGN+4, info ); - - if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE - || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) ) - membug("memory at %p corrupted: underflow=%02x (%s)\n", - p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info ); - if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE ) - membug("memory at %p corrupted: overflow=%02x (%s)\n", - p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info ); - return e; -} - - -/**************** - * free the entry and the memory (replaces free) - */ -static void -free_entry( byte *p, const char *info ) -{ - struct memtbl_entry *e, *e2; - - check_allmem("add_entry"); - - e = check_mem(p, info); - if( DBG_MEMORY ) - log_debug( "%s frees %u bytes alloced by %s\n", - info, e->user_n, e->info->info ); - if( !e->inuse ) { - if( e->user_p == p + EXTRA_ALIGN+ 4 ) - membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 ); - else - membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 ); - } - - e->inuse = 0; - e->next = NULL; - if( !memtbl_unused ) - memtbl_unused = e; - else { - for(e2=memtbl_unused; e2->next; e2 = e2->next ) - ; - e2->next = e; - } - memset(p,'f', e->user_n+5); - free(p); -} - -static void -dump_entry(struct memtbl_entry *e ) -{ - unsigned n = e - memtbl; - - fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n", - n, e->inuse?'a':'u', e->count, e->user_p, e->user_n, - e->info->info, e->info->count ); - - -} - - -static void -dump_table_at_exit( void) -{ - if( DBG_MEMSTAT ) - dump_table(); -} - -static void -dump_table( void) -{ - unsigned n; - struct memtbl_entry *e; - ulong sum = 0, chunks =0; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { - if(e->inuse) { - dump_entry(e); - sum += e->user_n; - chunks++; - } - } - fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n", - sum, chunks ); -} - - -static void -check_allmem( const char *info ) -{ - unsigned n; - struct memtbl_entry *e; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) - if( e->inuse ) - check_mem(e->user_p-4-EXTRA_ALIGN, info); -} - -#endif /* M_DEBUG */ - -#if defined(M_DEBUG) || defined(M_GUARD) -static void -membug( const char *fmt, ... ) -{ - va_list arg_ptr ; - - fprintf(stderr, "\nMemory Error: " ) ; - va_start( arg_ptr, fmt ) ; - vfprintf(stderr,fmt,arg_ptr) ; - va_end(arg_ptr); - fflush(stderr); - #ifdef M_DEBUG - if( DBG_MEMSTAT ) - dump_table(); - #endif - abort(); -} -#endif - -void -m_print_stats( const char *prefix ) -{ - #ifdef M_DEBUG - unsigned n; - struct memtbl_entry *e; - ulong sum = 0, chunks =0; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { - if(e->inuse) { - sum += e->user_n; - chunks++; - } - } - - log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n", - prefix? prefix:"", prefix? ": ":"", sum, chunks ); - #elif defined(M_GUARD) - log_debug( "%s%smemstat: %8ld bytes\n", - prefix? prefix:"", prefix? ": ":"", used_memory ); - #endif -} - -void -m_dump_table( const char *prefix ) -{ - #if M_DEBUG - fprintf(stderr,"Memory-Table-Dump: %s\n", prefix); - dump_table(); - #endif - m_print_stats( prefix ); -} - - -static void -out_of_core(size_t n, int secure) -{ - log_fatal("out of %s memory while allocating %u bytes\n", - secure? "secure":"" ,(unsigned)n ); - -} - - - -/**************** - * Allocate memory of size n. - * Return NULL if we are out of memory. - */ -void * -g10_private_malloc( size_t n) -{ - char *p; - - #ifdef M_GUARD - if( !(p = malloc( n + EXTRA_ALIGN+5 )) ) - return NULL; - store_len(p,n,0); - used_memory += n; - p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; - return p+EXTRA_ALIGN+4; - #else /* fixme: This can be done with a macro */ - return malloc( n ); - #endif -} - -/**************** - * Allocate memory of size n. - * This function gives up if we do not have enough memory - */ -void * -FNAME(alloc)( size_t n FNAMEPRT ) -{ - char *p = g10_private_malloc( n ); - if( !p ) - out_of_core(n,0); - return p; -} - - -/**************** - * Allocate memory of size n from the secure memory pool. - * Return NULL if we are out of memory. - */ -void * -g10_private_malloc_secure( size_t n) -{ - char *p; - - #ifdef M_GUARD - if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) ) - return NULL; - store_len(p,n,1); - p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; - return p+EXTRA_ALIGN+4; - #else - return secmem_malloc( n ); - #endif -} - -/**************** - * Allocate memory of size n from the secure memory pool. - * This function gives up if we do not have enough memory - */ -void * -FNAME(alloc_secure)( size_t n FNAMEPRT ) -{ - char *p = g10_private_malloc_secure( n ); - if( !p ) - out_of_core(n,1); - return p; -} - -void * -FNAME(alloc_clear)( size_t n FNAMEPRT ) -{ - void *p; - p = FNAME(alloc)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - -void * -FNAME(alloc_secure_clear)( size_t n FNAMEPRT) -{ - void *p; - p = FNAME(alloc_secure)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - -/**************** - * realloc and clear the old space - * Return NULL if there is not enoug memory. - */ -void * -g10_private_realloc( void *a, size_t n ) -{ - #ifdef M_GUARD - unsigned char *p = a; - void *b; - size_t len = m_size(a); - - if( len >= n ) /* we don't shrink for now */ - return a; - if( p[-1] == MAGIC_SEC_BYTE ) - b = g10_private_malloc_secure(n); - else - b = g10_private_malloc(n); - if( !b ) - return NULL; - memset(p, 0, n ); - FNAME(check)(NULL FNAMEARG); - memcpy(b, a, len ); - FNAME(free)(p FNAMEARG); - return b; - #else - if( g10_private_is_secure(a) ) { - return secmem_realloc( a, n ); - } - else { - return realloc( a, n ); - } - #endif -} - - -/**************** - * realloc and clear the old space - */ -void * -FNAME(realloc)( void *a, size_t n FNAMEPRT ) -{ - void *b = g10_private_realloc( a, n ); - if( !b ) - out_of_core(n, g10_private_is_secure(a)); - return b; -} - - -/**************** - * Free a pointer - */ -void -FNAME(free)( void *a FNAMEPRT ) -{ - byte *p = a; - - if( !p ) - return; - #ifdef M_DEBUG - free_entry(p-EXTRA_ALIGN-4, info); - #elif M_GUARD - m_check(p); - if( g10_private_is_secure(a) ) - secmem_free(p-EXTRA_ALIGN-4); - else { - used_memory -= m_size(a); - free(p-EXTRA_ALIGN-4); - } - #else - if( g10_private_is_secure(a) ) - secmem_free(p); - else - free(p); - #endif -} - -void -g10_private_free( void *a ) -{ - m_free(a); -} - -void -FNAME(check)( const void *a FNAMEPRT ) -{ - #ifdef M_GUARD - const byte *p = a; - - #ifdef M_DEBUG - if( p ) - check_mem(p-EXTRA_ALIGN-4, info); - else - check_allmem(info); - #else - if( !p ) - return; - if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) ) - membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] ); - else if( p[m_size(p)] != MAGIC_END_BYTE ) - membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] ); - #endif - #endif -} - - -void -g10_private_check_heap( const void *p ) -{ - m_check(p); -} - - -size_t -m_size( const void *a ) -{ - #ifndef M_GUARD - log_debug("Ooops, m_size called\n"); - return 0; - #else - const byte *p = a; - size_t n; - - #ifdef M_DEBUG - n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n; - #else - n = ((byte*)p)[-4]; - n |= ((byte*)p)[-3] << 8; - n |= ((byte*)p)[-2] << 16; - #endif - return n; - #endif -} - - -#if 0 /* not used */ -/**************** - * Make a copy of the memory block at a - */ -void * -FNAME(copy)( const void *a FNAMEPRT ) -{ - void *b; - size_t n; - - if( !a ) - return NULL; - - n = m_size(a); Aiiiih woher nehmen - if( g10_private_is_secure(a) ) - b = FNAME(alloc_secure)(n FNAMEARG); - else - b = FNAME(alloc)(n FNAMEARG); - memcpy(b, a, n ); - return b; -} -#endif - -char * -FNAME(strdup)( const char *a FNAMEPRT ) -{ - size_t n = strlen(a); - char *p = FNAME(alloc)(n+1 FNAMEARG); - strcpy(p, a); - return p; -} - -int -m_is_secure( const void *a ) -{ - return g10_private_is_secure(a); -} - - |