raw
mpi-genesis~            1 /* memory.c  -	memory allocation
mpi-genesis~ 2 * Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
mpi-genesis~ 3 *
mpi-genesis~ 4 * This file is part of GnuPG.
mpi-genesis~ 5 *
mpi-genesis~ 6 * GnuPG is free software; you can redistribute it and/or modify
mpi-genesis~ 7 * it under the terms of the GNU General Public License as published by
mpi-genesis~ 8 * the Free Software Foundation; either version 3 of the License, or
mpi-genesis~ 9 * (at your option) any later version.
mpi-genesis~ 10 *
mpi-genesis~ 11 * GnuPG is distributed in the hope that it will be useful,
mpi-genesis~ 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mpi-genesis~ 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
mpi-genesis~ 14 * GNU General Public License for more details.
mpi-genesis~ 15 *
mpi-genesis~ 16 * You should have received a copy of the GNU General Public License
mpi-genesis~ 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
mpi-genesis~ 18 *
mpi-genesis~ 19 *
mpi-genesis~ 20 * We use our own memory allocation functions instead of plain malloc(),
mpi-genesis~ 21 * so that we can provide some special enhancements:
mpi-genesis~ 22 * a) functions to provide memory from a secure memory.
mpi-genesis~ 23 * b) by looking at the requested allocation size we
mpi-genesis~ 24 * can reuse memory very quickly (e.g. MPI storage)
mpi-genesis~ 25 * (really needed?)
mpi-genesis~ 26 * c) memory usage reporting if compiled with M_DEBUG
mpi-genesis~ 27 * d) memory checking if compiled with M_GUARD
mpi-genesis~ 28 */
mpi-genesis~ 29
mpi-genesis~ 30 #include <config.h>
mpi-genesis~ 31 #include <stdio.h>
mpi-genesis~ 32 #include <stdlib.h>
mpi-genesis~ 33 #include <string.h>
mpi-genesis~ 34 #include <stdarg.h>
mpi-genesis~ 35
mpi-genesis~ 36 #include "types.h"
mpi-genesis~ 37 #include "memory.h"
mpi-genesis~ 38 #include "util.h"
mpi-genesis~ 39
mpi-genesis~ 40
mpi-genesis~ 41 #define MAGIC_NOR_BYTE 0x55
mpi-genesis~ 42 #define MAGIC_SEC_BYTE 0xcc
mpi-genesis~ 43 #define MAGIC_END_BYTE 0xaa
mpi-genesis~ 44
mpi-genesis~ 45 /* This is a very crude alignment check which does not work on all CPUs
mpi-genesis~ 46 * IIRC, I once introduced it for testing on an Alpha. We should better
mpi-genesis~ 47 * replace this guard stuff with one provided by a modern malloc library
mpi-genesis~ 48 */
mpi-genesis~ 49 #if SIZEOF_UNSIGNED_LONG == 8
mpi-genesis~ 50 #define EXTRA_ALIGN 4
mpi-genesis~ 51 #else
mpi-genesis~ 52 #define EXTRA_ALIGN 0
mpi-genesis~ 53 #endif
mpi-genesis~ 54
mpi-genesis~ 55 #if defined(M_DEBUG) || defined(M_GUARD)
mpi-genesis~ 56 static void membug( const char *fmt, ... );
mpi-genesis~ 57 #endif
mpi-genesis~ 58
mpi-genesis~ 59 #ifdef M_DEBUG
mpi-genesis~ 60
mpi-genesis~ 61 #ifndef M_GUARD
mpi-genesis~ 62 #define M_GUARD 1
mpi-genesis~ 63 #endif
mpi-genesis~ 64 #undef xmalloc
mpi-genesis~ 65 #undef xtrymalloc
mpi-genesis~ 66 #undef xmalloc_clear
mpi-genesis~ 67 #undef xmalloc_secure
mpi-genesis~ 68 #undef xmalloc_secure_clear
mpi-genesis~ 69 #undef xrealloc
mpi-genesis~ 70 #undef xfree
mpi-genesis~ 71 #undef m_check
mpi-genesis~ 72 #undef xstrdup
mpi-genesis~ 73 #undef xtrystrdup
mpi-genesis~ 74 #define FNAME(a) m_debug_ ##a
mpi-genesis~ 75 #define FNAMEX(a) m_debug_ ##a
mpi-genesis~ 76 #define FNAMEXM(a) m_debug_ ##a
mpi-genesis~ 77 #define FNAMEPRT , const char *info
mpi-genesis~ 78 #define FNAMEARG , info
mpi-genesis~ 79 #ifndef __riscos__
mpi-genesis~ 80 #define store_len(p,n,m) do { add_entry(p,n,m, \
mpi-genesis~ 81 info, __FUNCTION__); } while(0)
mpi-genesis~ 82 #else
mpi-genesis~ 83 #define store_len(p,n,m) do { add_entry(p,n,m, \
mpi-genesis~ 84 info, __func__ ); } while(0)
mpi-genesis~ 85 #endif
mpi-genesis~ 86 #else
mpi-genesis~ 87 #define FNAME(a) m_ ##a
mpi-genesis~ 88 #define FNAMEX(a) x ##a
mpi-genesis~ 89 #define FNAMEXM(a) xm ##a
mpi-genesis~ 90 #define FNAMEPRT
mpi-genesis~ 91 #define FNAMEARG
mpi-genesis~ 92 #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
mpi-genesis~ 93 ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
mpi-genesis~ 94 ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
mpi-genesis~ 95 ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
mpi-genesis~ 96 : MAGIC_NOR_BYTE; \
mpi-genesis~ 97 } while(0)
mpi-genesis~ 98 #endif
mpi-genesis~ 99
mpi-genesis~ 100
mpi-genesis~ 101 #ifdef M_GUARD
mpi-genesis~ 102 static long used_memory;
mpi-genesis~ 103 #endif
mpi-genesis~ 104
mpi-genesis~ 105 #ifdef M_DEBUG /* stuff used for memory debuging */
mpi-genesis~ 106
mpi-genesis~ 107 struct info_entry {
mpi-genesis~ 108 struct info_entry *next;
mpi-genesis~ 109 unsigned count; /* call count */
mpi-genesis~ 110 const char *info; /* the reference to the info string */
mpi-genesis~ 111 };
mpi-genesis~ 112
mpi-genesis~ 113 struct memtbl_entry {
mpi-genesis~ 114 const void *user_p; /* for reference: the pointer given to the user */
mpi-genesis~ 115 size_t user_n; /* length requested by the user */
mpi-genesis~ 116 struct memtbl_entry *next; /* to build a list of unused entries */
mpi-genesis~ 117 const struct info_entry *info; /* points into the table with */
mpi-genesis~ 118 /* the info strings */
mpi-genesis~ 119 unsigned inuse:1; /* this entry is in use */
mpi-genesis~ 120 unsigned count:31;
mpi-genesis~ 121 };
mpi-genesis~ 122
mpi-genesis~ 123
mpi-genesis~ 124 #define INFO_BUCKETS 53
mpi-genesis~ 125 #define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
mpi-genesis~ 126 static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
mpi-genesis~ 127
mpi-genesis~ 128 static struct memtbl_entry *memtbl; /* the table with the memory info */
mpi-genesis~ 129 static unsigned memtbl_size; /* number of allocated entries */
mpi-genesis~ 130 static unsigned memtbl_len; /* number of used entries */
mpi-genesis~ 131 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
mpi-genesis~ 132
mpi-genesis~ 133 static void dump_table_at_exit(void);
mpi-genesis~ 134 static void dump_table(void);
mpi-genesis~ 135 static void check_allmem( const char *info );
mpi-genesis~ 136
mpi-genesis~ 137 /****************
mpi-genesis~ 138 * Put the new P into the debug table and return a pointer to the table entry.
mpi-genesis~ 139 * mode is true for security. BY is the name of the function which called us.
mpi-genesis~ 140 */
mpi-genesis~ 141 static void
mpi-genesis~ 142 add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
mpi-genesis~ 143 {
mpi-genesis~ 144 unsigned index;
mpi-genesis~ 145 struct memtbl_entry *e;
mpi-genesis~ 146 struct info_entry *ie;
mpi-genesis~ 147
mpi-genesis~ 148 if( memtbl_len < memtbl_size )
mpi-genesis~ 149 index = memtbl_len++;
mpi-genesis~ 150 else {
mpi-genesis~ 151 struct memtbl_entry *e;
mpi-genesis~ 152 /* look for a used entry in the table. We take the first one,
mpi-genesis~ 153 * so that freed entries remain as long as possible in the table
mpi-genesis~ 154 * (free appends a new one)
mpi-genesis~ 155 */
mpi-genesis~ 156 if( (e = memtbl_unused) ) {
mpi-genesis~ 157 index = e - memtbl;
mpi-genesis~ 158 memtbl_unused = e->next;
mpi-genesis~ 159 e->next = NULL;
mpi-genesis~ 160 }
mpi-genesis~ 161 else { /* no free entries in the table: extend the table */
mpi-genesis~ 162 if( !memtbl_size ) { /* first time */
mpi-genesis~ 163 memtbl_size = 100;
mpi-genesis~ 164 if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
mpi-genesis~ 165 membug("memory debug table malloc failed\n");
mpi-genesis~ 166 index = 0;
mpi-genesis~ 167 memtbl_len = 1;
mpi-genesis~ 168 atexit( dump_table_at_exit );
mpi-genesis~ 169 }
mpi-genesis~ 170 else { /* realloc */
mpi-genesis~ 171 unsigned n = memtbl_size / 4; /* enlarge by 25% */
mpi-genesis~ 172 if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
mpi-genesis~ 173 membug("memory debug table realloc failed\n");
mpi-genesis~ 174 memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
mpi-genesis~ 175 memtbl_size += n;
mpi-genesis~ 176 index = memtbl_len++;
mpi-genesis~ 177 }
mpi-genesis~ 178 }
mpi-genesis~ 179 }
mpi-genesis~ 180 e = memtbl+index;
mpi-genesis~ 181 if( e->inuse )
mpi-genesis~ 182 membug("Ooops: entry %u is flagged as in use\n", index);
mpi-genesis~ 183 e->user_p = p + EXTRA_ALIGN + 4;
mpi-genesis~ 184 e->user_n = n;
mpi-genesis~ 185 e->count++;
mpi-genesis~ 186 if( e->next )
mpi-genesis~ 187 membug("Ooops: entry is in free entry list\n");
mpi-genesis~ 188 /* do we already have this info string */
mpi-genesis~ 189 for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
mpi-genesis~ 190 if( ie->info == info )
mpi-genesis~ 191 break;
mpi-genesis~ 192 if( !ie ) { /* no: make a new entry */
mpi-genesis~ 193 if( !(ie = malloc( sizeof *ie )) )
mpi-genesis~ 194 membug("can't allocate info entry\n");
mpi-genesis~ 195 ie->next = info_strings[info_hash(info)];
mpi-genesis~ 196 info_strings[info_hash(info)] = ie;
mpi-genesis~ 197 ie->info = info;
mpi-genesis~ 198 ie->count = 0;
mpi-genesis~ 199 }
mpi-genesis~ 200 ie->count++;
mpi-genesis~ 201 e->info = ie;
mpi-genesis~ 202 e->inuse = 1;
mpi-genesis~ 203
mpi-genesis~ 204 /* put the index at the start of the memory */
mpi-genesis~ 205 p[EXTRA_ALIGN+0] = index;
mpi-genesis~ 206 p[EXTRA_ALIGN+1] = index >> 8 ;
mpi-genesis~ 207 p[EXTRA_ALIGN+2] = index >> 16 ;
mpi-genesis~ 208 p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
mpi-genesis~ 209 if( DBG_MEMORY )
mpi-genesis~ 210 log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
mpi-genesis~ 211 }
mpi-genesis~ 212
mpi-genesis~ 213
mpi-genesis~ 214
mpi-genesis~ 215 /****************
mpi-genesis~ 216 * Check that the memory block is correct. The magic byte has already been
mpi-genesis~ 217 * checked. Checks which are done here:
mpi-genesis~ 218 * - see whether the index points into our memory table
mpi-genesis~ 219 * - see whether P is the same as the one stored in the table
mpi-genesis~ 220 * - see whether we have already freed this block.
mpi-genesis~ 221 */
mpi-genesis~ 222 struct memtbl_entry *
mpi-genesis~ 223 check_mem( const byte *p, const char *info )
mpi-genesis~ 224 {
mpi-genesis~ 225 unsigned n;
mpi-genesis~ 226 struct memtbl_entry *e;
mpi-genesis~ 227
mpi-genesis~ 228 n = p[EXTRA_ALIGN+0];
mpi-genesis~ 229 n |= p[EXTRA_ALIGN+1] << 8;
mpi-genesis~ 230 n |= p[EXTRA_ALIGN+2] << 16;
mpi-genesis~ 231
mpi-genesis~ 232 if( n >= memtbl_len )
mpi-genesis~ 233 membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
mpi-genesis~ 234 p+EXTRA_ALIGN+4, n, memtbl_len, info );
mpi-genesis~ 235 e = memtbl+n;
mpi-genesis~ 236
mpi-genesis~ 237 if( e->user_p != p+EXTRA_ALIGN+4 )
mpi-genesis~ 238 membug("memory at %p corrupted: reference mismatch (%s)\n",
mpi-genesis~ 239 p+EXTRA_ALIGN+4, info );
mpi-genesis~ 240 if( !e->inuse )
mpi-genesis~ 241 membug("memory at %p corrupted: marked as free (%s)\n",
mpi-genesis~ 242 p+EXTRA_ALIGN+4, info );
mpi-genesis~ 243
mpi-genesis~ 244 if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
mpi-genesis~ 245 || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
mpi-genesis~ 246 membug("memory at %p corrupted: underflow=%02x (%s)\n",
mpi-genesis~ 247 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
mpi-genesis~ 248 if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
mpi-genesis~ 249 membug("memory at %p corrupted: overflow=%02x (%s)\n",
mpi-genesis~ 250 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
mpi-genesis~ 251 return e;
mpi-genesis~ 252 }
mpi-genesis~ 253
mpi-genesis~ 254
mpi-genesis~ 255 /****************
mpi-genesis~ 256 * free the entry and the memory (replaces free)
mpi-genesis~ 257 */
mpi-genesis~ 258 static void
mpi-genesis~ 259 free_entry( byte *p, const char *info )
mpi-genesis~ 260 {
mpi-genesis~ 261 struct memtbl_entry *e, *e2;
mpi-genesis~ 262
mpi-genesis~ 263 check_allmem("add_entry");
mpi-genesis~ 264
mpi-genesis~ 265 e = check_mem(p, info);
mpi-genesis~ 266 if( DBG_MEMORY )
mpi-genesis~ 267 log_debug( "%s frees %u bytes alloced by %s\n",
mpi-genesis~ 268 info, e->user_n, e->info->info );
mpi-genesis~ 269 if( !e->inuse ) {
mpi-genesis~ 270 if( e->user_p == p + EXTRA_ALIGN+ 4 )
mpi-genesis~ 271 membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
mpi-genesis~ 272 else
mpi-genesis~ 273 membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
mpi-genesis~ 274 }
mpi-genesis~ 275
mpi-genesis~ 276 e->inuse = 0;
mpi-genesis~ 277 e->next = NULL;
mpi-genesis~ 278 if( !memtbl_unused )
mpi-genesis~ 279 memtbl_unused = e;
mpi-genesis~ 280 else {
mpi-genesis~ 281 for(e2=memtbl_unused; e2->next; e2 = e2->next )
mpi-genesis~ 282 ;
mpi-genesis~ 283 e2->next = e;
mpi-genesis~ 284 }
mpi-genesis~ 285 if( m_is_secure(p+EXTRA_ALIGN+4) )
mpi-genesis~ 286 secmem_free(p);
mpi-genesis~ 287 else {
mpi-genesis~ 288 memset(p,'f', e->user_n+5);
mpi-genesis~ 289 free(p);
mpi-genesis~ 290 }
mpi-genesis~ 291 }
mpi-genesis~ 292
mpi-genesis~ 293 static void
mpi-genesis~ 294 dump_entry(struct memtbl_entry *e )
mpi-genesis~ 295 {
mpi-genesis~ 296 unsigned n = e - memtbl;
mpi-genesis~ 297
mpi-genesis~ 298 fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
mpi-genesis~ 299 n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
mpi-genesis~ 300 e->info->info, e->info->count );
mpi-genesis~ 301
mpi-genesis~ 302
mpi-genesis~ 303 }
mpi-genesis~ 304
mpi-genesis~ 305
mpi-genesis~ 306 static void
mpi-genesis~ 307 dump_table_at_exit( void)
mpi-genesis~ 308 {
mpi-genesis~ 309 if( DBG_MEMSTAT )
mpi-genesis~ 310 dump_table();
mpi-genesis~ 311 }
mpi-genesis~ 312
mpi-genesis~ 313 static void
mpi-genesis~ 314 dump_table( void)
mpi-genesis~ 315 {
mpi-genesis~ 316 unsigned n;
mpi-genesis~ 317 struct memtbl_entry *e;
mpi-genesis~ 318 ulong sum = 0, chunks =0;
mpi-genesis~ 319
mpi-genesis~ 320 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
mpi-genesis~ 321 if(e->inuse) {
mpi-genesis~ 322 dump_entry(e);
mpi-genesis~ 323 sum += e->user_n;
mpi-genesis~ 324 chunks++;
mpi-genesis~ 325 }
mpi-genesis~ 326 }
mpi-genesis~ 327 fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
mpi-genesis~ 328 sum, chunks );
mpi-genesis~ 329 }
mpi-genesis~ 330
mpi-genesis~ 331
mpi-genesis~ 332 static void
mpi-genesis~ 333 check_allmem( const char *info )
mpi-genesis~ 334 {
mpi-genesis~ 335 unsigned n;
mpi-genesis~ 336 struct memtbl_entry *e;
mpi-genesis~ 337
mpi-genesis~ 338 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
mpi-genesis~ 339 if( e->inuse ) {
mpi-genesis~ 340 #ifndef __riscos__
mpi-genesis~ 341 check_mem(e->user_p-4-EXTRA_ALIGN, info);
mpi-genesis~ 342 #else
mpi-genesis~ 343 check_mem((const byte *) e->user_p-4-EXTRA_ALIGN, info);
mpi-genesis~ 344 #endif
mpi-genesis~ 345 }
mpi-genesis~ 346 }
mpi-genesis~ 347 }
mpi-genesis~ 348
mpi-genesis~ 349 #endif /* M_DEBUG */
mpi-genesis~ 350
mpi-genesis~ 351 #if defined(M_DEBUG) || defined(M_GUARD)
mpi-genesis~ 352 static void
mpi-genesis~ 353 membug( const char *fmt, ... )
mpi-genesis~ 354 {
mpi-genesis~ 355 va_list arg_ptr ;
mpi-genesis~ 356
mpi-genesis~ 357 fprintf(stderr, "\nMemory Error: " ) ;
mpi-genesis~ 358 va_start( arg_ptr, fmt ) ;
mpi-genesis~ 359 vfprintf(stderr,fmt,arg_ptr) ;
mpi-genesis~ 360 va_end(arg_ptr);
mpi-genesis~ 361 fflush(stderr);
mpi-genesis~ 362 #ifdef M_DEBUG
mpi-genesis~ 363 if( DBG_MEMSTAT )
mpi-genesis~ 364 dump_table();
mpi-genesis~ 365 #endif
mpi-genesis~ 366 abort();
mpi-genesis~ 367 }
mpi-genesis~ 368 #endif
mpi-genesis~ 369
mpi-genesis~ 370 void
mpi-genesis~ 371 m_print_stats( const char *prefix )
mpi-genesis~ 372 {
mpi-genesis~ 373 #ifdef M_DEBUG
mpi-genesis~ 374 unsigned n;
mpi-genesis~ 375 struct memtbl_entry *e;
mpi-genesis~ 376 ulong sum = 0, chunks =0;
mpi-genesis~ 377
mpi-genesis~ 378 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
mpi-genesis~ 379 if(e->inuse) {
mpi-genesis~ 380 sum += e->user_n;
mpi-genesis~ 381 chunks++;
mpi-genesis~ 382 }
mpi-genesis~ 383 }
mpi-genesis~ 384
mpi-genesis~ 385 log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
mpi-genesis~ 386 prefix? prefix:"", prefix? ": ":"", sum, chunks );
mpi-genesis~ 387 #elif defined(M_GUARD)
mpi-genesis~ 388 log_debug( "%s%smemstat: %8ld bytes\n",
mpi-genesis~ 389 prefix? prefix:"", prefix? ": ":"", used_memory );
mpi-genesis~ 390 #endif
mpi-genesis~ 391 }
mpi-genesis~ 392
mpi-genesis~ 393 void
mpi-genesis~ 394 m_dump_table( const char *prefix )
mpi-genesis~ 395 {
mpi-genesis~ 396 #ifdef M_DEBUG
mpi-genesis~ 397 fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
mpi-genesis~ 398 dump_table();
mpi-genesis~ 399 #endif
mpi-genesis~ 400 m_print_stats( prefix );
mpi-genesis~ 401 }
mpi-genesis~ 402
mpi-genesis~ 403
mpi-genesis~ 404 static void
mpi-genesis~ 405 out_of_core(size_t n, int secure)
mpi-genesis~ 406 {
mpi-genesis~ 407 log_error ("out of %s memory while allocating %u bytes\n",
mpi-genesis~ 408 secure? "secure":"" ,(unsigned)n );
mpi-genesis~ 409 if (secure) {
mpi-genesis~ 410 /*secmem_dump_stats ();*/
mpi-genesis~ 411 log_info ("(this may be caused by too many secret keys used "
mpi-genesis~ 412 "simultaneously or due to excessive large key sizes)\n");
mpi-genesis~ 413 }
mpi-genesis~ 414 #if defined(M_GUARD) && defined(__riscos__)
mpi-genesis~ 415 abort();
mpi-genesis~ 416 #endif
mpi-genesis~ 417 exit (2);
mpi-genesis~ 418 }
mpi-genesis~ 419
mpi-genesis~ 420 /****************
mpi-genesis~ 421 * Allocate memory of size n.
mpi-genesis~ 422 * This function gives up if we do not have enough memory
mpi-genesis~ 423 */
mpi-genesis~ 424 void *
mpi-genesis~ 425 FNAMEXM(alloc)( size_t n FNAMEPRT )
mpi-genesis~ 426 {
mpi-genesis~ 427 char *p;
mpi-genesis~ 428
mpi-genesis~ 429 #ifdef M_GUARD
mpi-genesis~ 430 if(!n)
mpi-genesis~ 431 out_of_core(n,0); /* should never happen */
mpi-genesis~ 432 if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
mpi-genesis~ 433 out_of_core(n,0);
mpi-genesis~ 434 store_len(p,n,0);
mpi-genesis~ 435 used_memory += n;
mpi-genesis~ 436 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
mpi-genesis~ 437 return p+EXTRA_ALIGN+4;
mpi-genesis~ 438 #else
mpi-genesis~ 439 /* mallocing zero bytes is undefined by ISO-C, so we better make
mpi-genesis~ 440 sure that it won't happen */
mpi-genesis~ 441 if (!n)
mpi-genesis~ 442 n = 1;
mpi-genesis~ 443 if( !(p = malloc( n )) )
mpi-genesis~ 444 out_of_core(n,0);
mpi-genesis~ 445 return p;
mpi-genesis~ 446 #endif
mpi-genesis~ 447 }
mpi-genesis~ 448
mpi-genesis~ 449 /* Allocate memory of size n. This function returns NULL if we do not
mpi-genesis~ 450 have enough memory. */
mpi-genesis~ 451 void *
mpi-genesis~ 452 FNAMEX(trymalloc)(size_t n FNAMEPRT)
mpi-genesis~ 453 {
mpi-genesis~ 454 #ifdef M_GUARD
mpi-genesis~ 455 char *p;
mpi-genesis~ 456
mpi-genesis~ 457 if (!n)
mpi-genesis~ 458 n = 1;
mpi-genesis~ 459 p = malloc (n + EXTRA_ALIGN+5);
mpi-genesis~ 460 if (!p)
mpi-genesis~ 461 return NULL;
mpi-genesis~ 462 store_len(p,n,0);
mpi-genesis~ 463 used_memory += n;
mpi-genesis~ 464 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
mpi-genesis~ 465 return p+EXTRA_ALIGN+4;
mpi-genesis~ 466 #else
mpi-genesis~ 467 /* Mallocing zero bytes is undefined by ISO-C, so we better make
mpi-genesis~ 468 sure that it won't happen. */
mpi-genesis~ 469 return malloc (n? n: 1);
mpi-genesis~ 470 #endif
mpi-genesis~ 471 }
mpi-genesis~ 472
mpi-genesis~ 473 /****************
mpi-genesis~ 474 * Allocate memory of size n from the secure memory pool.
mpi-genesis~ 475 * This function gives up if we do not have enough memory
mpi-genesis~ 476 */
mpi-genesis~ 477 void *
mpi-genesis~ 478 FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
mpi-genesis~ 479 {
mpi-genesis~ 480 char *p;
mpi-genesis~ 481
mpi-genesis~ 482 #ifdef M_GUARD
mpi-genesis~ 483 if(!n)
mpi-genesis~ 484 out_of_core(n,1); /* should never happen */
mpi-genesis~ 485 if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
mpi-genesis~ 486 out_of_core(n,1);
mpi-genesis~ 487 store_len(p,n,1);
mpi-genesis~ 488 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
mpi-genesis~ 489 return p+EXTRA_ALIGN+4;
mpi-genesis~ 490 #else
mpi-genesis~ 491 /* mallocing zero bytes is undefined by ISO-C, so we better make
mpi-genesis~ 492 sure that it won't happen */
mpi-genesis~ 493 if (!n)
mpi-genesis~ 494 n = 1;
mpi-genesis~ 495 if( !(p = secmem_malloc( n )) )
mpi-genesis~ 496 out_of_core(n,1);
mpi-genesis~ 497 return p;
mpi-genesis~ 498 #endif
mpi-genesis~ 499 }
mpi-genesis~ 500
mpi-genesis~ 501 void *
mpi-genesis~ 502 FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
mpi-genesis~ 503 {
mpi-genesis~ 504 void *p;
mpi-genesis~ 505 p = FNAMEXM(alloc)( n FNAMEARG );
mpi-genesis~ 506 memset(p, 0, n );
mpi-genesis~ 507 return p;
mpi-genesis~ 508 }
mpi-genesis~ 509
mpi-genesis~ 510 void *
mpi-genesis~ 511 FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
mpi-genesis~ 512 {
mpi-genesis~ 513 void *p;
mpi-genesis~ 514 p = FNAMEXM(alloc_secure)( n FNAMEARG );
mpi-genesis~ 515 memset(p, 0, n );
mpi-genesis~ 516 return p;
mpi-genesis~ 517 }
mpi-genesis~ 518
mpi-genesis~ 519
mpi-genesis~ 520 /****************
mpi-genesis~ 521 * realloc and clear the old space
mpi-genesis~ 522 */
mpi-genesis~ 523 void *
mpi-genesis~ 524 FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
mpi-genesis~ 525 {
mpi-genesis~ 526 void *b;
mpi-genesis~ 527
mpi-genesis~ 528 #ifdef M_GUARD
mpi-genesis~ 529 if( a ) {
mpi-genesis~ 530 #error "--enable-m-guard does not currently work"
mpi-genesis~ 531 unsigned char *p = a;
mpi-genesis~ 532 size_t len = m_size(a);
mpi-genesis~ 533
mpi-genesis~ 534 if( len >= n ) /* we don't shrink for now */
mpi-genesis~ 535 return a;
mpi-genesis~ 536 if( p[-1] == MAGIC_SEC_BYTE )
mpi-genesis~ 537 b = FNAME(alloc_secure_clear)(n FNAMEARG);
mpi-genesis~ 538 else
mpi-genesis~ 539 b = FNAME(alloc_clear)(n FNAMEARG);
mpi-genesis~ 540 FNAME(check)(NULL FNAMEARG);
mpi-genesis~ 541 memcpy(b, a, len );
mpi-genesis~ 542 FNAME(free)(p FNAMEARG);
mpi-genesis~ 543 }
mpi-genesis~ 544 else
mpi-genesis~ 545 b = FNAME(alloc)(n FNAMEARG);
mpi-genesis~ 546 #else
mpi-genesis~ 547 if( m_is_secure(a) ) {
mpi-genesis~ 548 if( !(b = secmexrealloc( a, n )) )
mpi-genesis~ 549 out_of_core(n,1);
mpi-genesis~ 550 }
mpi-genesis~ 551 else {
mpi-genesis~ 552 if( !(b = realloc( a, n )) )
mpi-genesis~ 553 out_of_core(n,0);
mpi-genesis~ 554 }
mpi-genesis~ 555 #endif
mpi-genesis~ 556
mpi-genesis~ 557 return b;
mpi-genesis~ 558 }
mpi-genesis~ 559
mpi-genesis~ 560
mpi-genesis~ 561
mpi-genesis~ 562 /****************
mpi-genesis~ 563 * Free a pointer
mpi-genesis~ 564 */
mpi-genesis~ 565 void
mpi-genesis~ 566 FNAMEX(free)( void *a FNAMEPRT )
mpi-genesis~ 567 {
mpi-genesis~ 568 byte *p = a;
mpi-genesis~ 569
mpi-genesis~ 570 if( !p )
mpi-genesis~ 571 return;
mpi-genesis~ 572 #ifdef M_DEBUG
mpi-genesis~ 573 free_entry(p-EXTRA_ALIGN-4, info);
mpi-genesis~ 574 #elif defined M_GUARD
mpi-genesis~ 575 m_check(p);
mpi-genesis~ 576 if( m_is_secure(a) )
mpi-genesis~ 577 secmem_free(p-EXTRA_ALIGN-4);
mpi-genesis~ 578 else {
mpi-genesis~ 579 used_memory -= m_size(a);
mpi-genesis~ 580 free(p-EXTRA_ALIGN-4);
mpi-genesis~ 581 }
mpi-genesis~ 582 #else
mpi-genesis~ 583 if( m_is_secure(a) )
mpi-genesis~ 584 secmem_free(p);
mpi-genesis~ 585 else
mpi-genesis~ 586 free(p);
mpi-genesis~ 587 #endif
mpi-genesis~ 588 }
mpi-genesis~ 589
mpi-genesis~ 590
mpi-genesis~ 591 void
mpi-genesis~ 592 FNAME(check)( const void *a FNAMEPRT )
mpi-genesis~ 593 {
mpi-genesis~ 594 #ifdef M_GUARD
mpi-genesis~ 595 const byte *p = a;
mpi-genesis~ 596
mpi-genesis~ 597 #ifdef M_DEBUG
mpi-genesis~ 598 if( p )
mpi-genesis~ 599 check_mem(p-EXTRA_ALIGN-4, info);
mpi-genesis~ 600 else
mpi-genesis~ 601 check_allmem(info);
mpi-genesis~ 602 #else
mpi-genesis~ 603 if( !p )
mpi-genesis~ 604 return;
mpi-genesis~ 605 if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
mpi-genesis~ 606 membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
mpi-genesis~ 607 else if( p[m_size(p)] != MAGIC_END_BYTE )
mpi-genesis~ 608 membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
mpi-genesis~ 609 #endif
mpi-genesis~ 610 #endif
mpi-genesis~ 611 }
mpi-genesis~ 612
mpi-genesis~ 613
mpi-genesis~ 614 size_t
mpi-genesis~ 615 m_size( const void *a )
mpi-genesis~ 616 {
mpi-genesis~ 617 #ifndef M_GUARD
mpi-genesis~ 618 log_debug("dummy m_size called\n");
mpi-genesis~ 619 return 0;
mpi-genesis~ 620 #else
mpi-genesis~ 621 const byte *p = a;
mpi-genesis~ 622 size_t n;
mpi-genesis~ 623
mpi-genesis~ 624 #ifdef M_DEBUG
mpi-genesis~ 625 n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
mpi-genesis~ 626 #else
mpi-genesis~ 627 n = ((byte*)p)[-4];
mpi-genesis~ 628 n |= ((byte*)p)[-3] << 8;
mpi-genesis~ 629 n |= ((byte*)p)[-2] << 16;
mpi-genesis~ 630 #endif
mpi-genesis~ 631 return n;
mpi-genesis~ 632 #endif
mpi-genesis~ 633 }
mpi-genesis~ 634
mpi-genesis~ 635
mpi-genesis~ 636 char *
mpi-genesis~ 637 FNAMEX(strdup)( const char *a FNAMEPRT )
mpi-genesis~ 638 {
mpi-genesis~ 639 size_t n = strlen(a);
mpi-genesis~ 640 char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
mpi-genesis~ 641 strcpy(p, a);
mpi-genesis~ 642 return p;
mpi-genesis~ 643 }
mpi-genesis~ 644
mpi-genesis~ 645 char *
mpi-genesis~ 646 FNAMEX(trystrdup)(const char *a FNAMEPRT)
mpi-genesis~ 647 {
mpi-genesis~ 648 size_t n = strlen (a);
mpi-genesis~ 649 char *p = FNAMEX(trymalloc)(n+1 FNAMEARG);
mpi-genesis~ 650 if (p)
mpi-genesis~ 651 strcpy (p, a);
mpi-genesis~ 652 return p;
mpi-genesis~ 653 }
mpi-genesis~ 654
mpi-genesis~ 655
mpi-genesis~ 656 /* Wrapper around xmalloc_clear to take the usual 2 arguments of a
mpi-genesis~ 657 calloc style function. */
mpi-genesis~ 658 void *
mpi-genesis~ 659 xcalloc (size_t n, size_t m)
mpi-genesis~ 660 {
mpi-genesis~ 661 size_t nbytes;
mpi-genesis~ 662
mpi-genesis~ 663 nbytes = n * m;
mpi-genesis~ 664 if (m && nbytes / m != n)
mpi-genesis~ 665 out_of_core (nbytes, 0);
mpi-genesis~ 666 return xmalloc_clear (nbytes);
mpi-genesis~ 667 }
mpi-genesis~ 668
mpi-genesis~ 669 /* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
mpi-genesis~ 670 of a calloc style function. */
mpi-genesis~ 671 void *
mpi-genesis~ 672 xcalloc_secure (size_t n, size_t m)
mpi-genesis~ 673 {
mpi-genesis~ 674 size_t nbytes;
mpi-genesis~ 675
mpi-genesis~ 676 nbytes = n * m;
mpi-genesis~ 677 if (m && nbytes / m != n)
mpi-genesis~ 678 out_of_core (nbytes, 1);
mpi-genesis~ 679 return xmalloc_secure_clear (nbytes);
mpi-genesis~ 680 }
mpi-genesis~ 681