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