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