aboutsummaryrefslogtreecommitdiffstats
path: root/util/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/memory.c')
-rw-r--r--util/memory.c651
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);
-}
-
-