00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef DEFAULT_CHECK_ACTION
00024 #define DEFAULT_CHECK_ACTION 1
00025 #endif
00026
00027
00028
00029
00030
00031
00032
00033
00034 static Void_t*
00035 #if __STD_C
00036 malloc_hook_ini(size_t sz, const __malloc_ptr_t caller)
00037 #else
00038 malloc_hook_ini(sz, caller)
00039 size_t sz; const __malloc_ptr_t caller;
00040 #endif
00041 {
00042 __malloc_hook = NULL;
00043 ptmalloc_init();
00044 return public_mALLOc(sz);
00045 }
00046
00047 static Void_t*
00048 #if __STD_C
00049 realloc_hook_ini(Void_t* ptr, size_t sz, const __malloc_ptr_t caller)
00050 #else
00051 realloc_hook_ini(ptr, sz, caller)
00052 Void_t* ptr; size_t sz; const __malloc_ptr_t caller;
00053 #endif
00054 {
00055 __malloc_hook = NULL;
00056 __realloc_hook = NULL;
00057 ptmalloc_init();
00058 return public_rEALLOc(ptr, sz);
00059 }
00060
00061 static Void_t*
00062 #if __STD_C
00063 memalign_hook_ini(size_t alignment, size_t sz, const __malloc_ptr_t caller)
00064 #else
00065 memalign_hook_ini(alignment, sz, caller)
00066 size_t alignment; size_t sz; const __malloc_ptr_t caller;
00067 #endif
00068 {
00069 __memalign_hook = NULL;
00070 ptmalloc_init();
00071 return public_mEMALIGn(alignment, sz);
00072 }
00073
00074
00075 static int check_action = DEFAULT_CHECK_ACTION;
00076
00077
00078 static int using_malloc_checking;
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 static int disallow_malloc_check;
00094
00095
00096
00097
00098
00099
00100 #define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
00101
00102
00103
00104
00105 static Void_t*
00106 internal_function
00107 #if __STD_C
00108 mem2mem_check(Void_t *ptr, size_t sz)
00109 #else
00110 mem2mem_check(ptr, sz) Void_t *ptr; size_t sz;
00111 #endif
00112 {
00113 mchunkptr p;
00114 unsigned char* m_ptr = (unsigned char*)BOUNDED_N(ptr, sz);
00115 size_t i;
00116
00117 if (!ptr)
00118 return ptr;
00119 p = mem2chunk(ptr);
00120 for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1);
00121 i > sz;
00122 i -= 0xFF) {
00123 if(i-sz < 0x100) {
00124 m_ptr[i] = (unsigned char)(i-sz);
00125 break;
00126 }
00127 m_ptr[i] = 0xFF;
00128 }
00129 m_ptr[sz] = MAGICBYTE(p);
00130 return (Void_t*)m_ptr;
00131 }
00132
00133
00134
00135
00136 static mchunkptr
00137 internal_function
00138 #if __STD_C
00139 mem2chunk_check(Void_t* mem)
00140 #else
00141 mem2chunk_check(mem) Void_t* mem;
00142 #endif
00143 {
00144 mchunkptr p;
00145 INTERNAL_SIZE_T sz, c;
00146 unsigned char magic;
00147
00148 if(!aligned_OK(mem)) return NULL;
00149 p = mem2chunk(mem);
00150 if( (char*)p>=mp_.sbrk_base &&
00151 (char*)p<(mp_.sbrk_base+main_arena.system_mem) ) {
00152
00153 if(chunk_is_mmapped(p) ||
00154 ( (sz = chunksize(p)),
00155 ((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) ) ||
00156 sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) ||
00157 ( !prev_inuse(p) && (p->prev_size&MALLOC_ALIGN_MASK ||
00158 (long)prev_chunk(p)<(long)mp_.sbrk_base ||
00159 next_chunk(prev_chunk(p))!=p) ))
00160 return NULL;
00161 magic = MAGICBYTE(p);
00162 for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
00163 if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
00164 }
00165 ((unsigned char*)p)[sz] ^= 0xFF;
00166 } else {
00167 unsigned long offset, page_mask = malloc_getpagesize-1;
00168
00169
00170
00171
00172 offset = (unsigned long)mem & page_mask;
00173 if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 &&
00174 offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 &&
00175 offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 &&
00176 offset<0x2000) ||
00177 !chunk_is_mmapped(p) || (p->size & PREV_INUSE) ||
00178 ( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
00179 ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
00180 return NULL;
00181 magic = MAGICBYTE(p);
00182 for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
00183 if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
00184 }
00185 ((unsigned char*)p)[sz] ^= 0xFF;
00186 }
00187 return p;
00188 }
00189
00190
00191
00192
00193 static int
00194 internal_function
00195 #if __STD_C
00196 top_check(void)
00197 #else
00198 top_check()
00199 #endif
00200 {
00201 mchunkptr t = top(&main_arena);
00202 char* brk, * new_brk;
00203 INTERNAL_SIZE_T front_misalign, sbrk_size;
00204 unsigned long pagesz = malloc_getpagesize;
00205
00206 if((char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem ||
00207 t == initial_top(&main_arena)) return 0;
00208
00209 if(check_action & 1)
00210 fprintf(stderr, "malloc: top chunk is corrupt\n");
00211 if(check_action & 2)
00212 abort();
00213
00214
00215 brk = MORECORE(0);
00216 front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
00217 if (front_misalign > 0)
00218 front_misalign = MALLOC_ALIGNMENT - front_misalign;
00219 sbrk_size = front_misalign + mp_.top_pad + MINSIZE;
00220 sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1));
00221 new_brk = (char*)(MORECORE (sbrk_size));
00222 if (new_brk == (char*)(MORECORE_FAILURE)) return -1;
00223
00224 if (__after_morecore_hook)
00225 (*__after_morecore_hook) ();
00226 main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
00227
00228 top(&main_arena) = (mchunkptr)(brk + front_misalign);
00229 set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
00230
00231 return 0;
00232 }
00233
00234 static Void_t*
00235 #if __STD_C
00236 malloc_check(size_t sz, const Void_t *caller)
00237 #else
00238 malloc_check(sz, caller) size_t sz; const Void_t *caller;
00239 #endif
00240 {
00241 Void_t *victim;
00242
00243 (void)mutex_lock(&main_arena.mutex);
00244 victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL;
00245 (void)mutex_unlock(&main_arena.mutex);
00246 return mem2mem_check(victim, sz);
00247 }
00248
00249 #if HAVE_MMAP
00250
00251 void
00252 internal_function
00253 #if __STD_C
00254 munmap_chunk(mchunkptr p);
00255 #else
00256 munmap_chunk();
00257 #endif
00258 #endif
00259
00260 static void
00261 #if __STD_C
00262 free_check(Void_t* mem, const Void_t *caller)
00263 #else
00264 free_check(mem, caller) Void_t* mem; const Void_t *caller;
00265 #endif
00266 {
00267 mchunkptr p;
00268
00269 if(!mem) return;
00270 (void)mutex_lock(&main_arena.mutex);
00271 p = mem2chunk_check(mem);
00272 if(!p) {
00273 (void)mutex_unlock(&main_arena.mutex);
00274 if(check_action & 1)
00275 fprintf(stderr, "free(): invalid pointer %p!\n", mem);
00276 if(check_action & 2)
00277 abort();
00278 return;
00279 }
00280 #if HAVE_MMAP
00281 if (chunk_is_mmapped(p)) {
00282 (void)mutex_unlock(&main_arena.mutex);
00283 munmap_chunk(p);
00284 return;
00285 }
00286 #endif
00287 #if 0
00288 memset(mem, 0, chunksize(p) - (SIZE_SZ+1));
00289 #endif
00290 _int_free(&main_arena, mem);
00291 (void)mutex_unlock(&main_arena.mutex);
00292 }
00293
00294 static Void_t*
00295 #if __STD_C
00296 realloc_check(Void_t* oldmem, size_t bytes, const Void_t *caller)
00297 #else
00298 realloc_check(oldmem, bytes, caller)
00299 Void_t* oldmem; size_t bytes; const Void_t *caller;
00300 #endif
00301 {
00302 mchunkptr oldp;
00303 INTERNAL_SIZE_T nb, oldsize;
00304 Void_t* newmem = 0;
00305
00306 if (oldmem == 0) return malloc_check(bytes, NULL);
00307 (void)mutex_lock(&main_arena.mutex);
00308 oldp = mem2chunk_check(oldmem);
00309 (void)mutex_unlock(&main_arena.mutex);
00310 if(!oldp) {
00311 if(check_action & 1)
00312 fprintf(stderr, "realloc(): invalid pointer %p!\n", oldmem);
00313 if(check_action & 2)
00314 abort();
00315 return malloc_check(bytes, NULL);
00316 }
00317 oldsize = chunksize(oldp);
00318
00319 checked_request2size(bytes+1, nb);
00320 (void)mutex_lock(&main_arena.mutex);
00321
00322 #if HAVE_MMAP
00323 if (chunk_is_mmapped(oldp)) {
00324 #if HAVE_MREMAP
00325 mchunkptr newp = mremap_chunk(oldp, nb);
00326 if(newp)
00327 newmem = chunk2mem(newp);
00328 else
00329 #endif
00330 {
00331
00332 if(oldsize - SIZE_SZ >= nb)
00333 newmem = oldmem;
00334 else {
00335
00336 if (top_check() >= 0)
00337 newmem = _int_malloc(&main_arena, bytes+1);
00338 if (newmem) {
00339 MALLOC_COPY(BOUNDED_N(newmem, bytes+1), oldmem, oldsize - 2*SIZE_SZ);
00340 munmap_chunk(oldp);
00341 }
00342 }
00343 }
00344 } else {
00345 #endif
00346 if (top_check() >= 0)
00347 newmem = _int_realloc(&main_arena, oldmem, bytes+1);
00348 #if 0
00349 if(newmem)
00350 newp = mem2chunk(newmem);
00351 nb = chunksize(newp);
00352 if(oldp<newp || oldp>=chunk_at_offset(newp, nb)) {
00353 memset((char*)oldmem + 2*sizeof(mbinptr), 0,
00354 oldsize - (2*sizeof(mbinptr)+2*SIZE_SZ+1));
00355 } else if(nb > oldsize+SIZE_SZ) {
00356 memset((char*)BOUNDED_N(chunk2mem(newp), bytes) + oldsize,
00357 0, nb - (oldsize+SIZE_SZ));
00358 }
00359 #endif
00360 #if HAVE_MMAP
00361 }
00362 #endif
00363 (void)mutex_unlock(&main_arena.mutex);
00364
00365 return mem2mem_check(newmem, bytes);
00366 }
00367
00368 static Void_t*
00369 #if __STD_C
00370 memalign_check(size_t alignment, size_t bytes, const Void_t *caller)
00371 #else
00372 memalign_check(alignment, bytes, caller)
00373 size_t alignment; size_t bytes; const Void_t *caller;
00374 #endif
00375 {
00376 INTERNAL_SIZE_T nb;
00377 Void_t* mem;
00378
00379 if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
00380 if (alignment < MINSIZE) alignment = MINSIZE;
00381
00382 checked_request2size(bytes+1, nb);
00383 (void)mutex_lock(&main_arena.mutex);
00384 mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
00385 NULL;
00386 (void)mutex_unlock(&main_arena.mutex);
00387 return mem2mem_check(mem, bytes);
00388 }
00389
00390
00391 void
00392 __malloc_check_init()
00393 {
00394 if (disallow_malloc_check) {
00395 disallow_malloc_check = 0;
00396 return;
00397 }
00398 using_malloc_checking = 1;
00399 __malloc_hook = malloc_check;
00400 __free_hook = free_check;
00401 __realloc_hook = realloc_check;
00402 __memalign_hook = memalign_check;
00403 if(check_action & 1)
00404 fprintf(stderr, "malloc: using debugging hooks\n");
00405 }
00406
00407 #ifndef NO_THREADS
00408
00409 # ifdef _LIBC
00410 # if USE___THREAD || (defined USE_TLS && !defined SHARED)
00411
00412 # define NO_STARTER
00413 # endif
00414 # endif
00415
00416 # ifdef NO_STARTER
00417 # undef NO_STARTER
00418 # else
00419
00420
00421
00422
00423 static Void_t*
00424 #if __STD_C
00425 malloc_starter(size_t sz, const Void_t *caller)
00426 #else
00427 malloc_starter(sz, caller) size_t sz; const Void_t *caller;
00428 #endif
00429 {
00430 Void_t* victim;
00431
00432 victim = _int_malloc(&main_arena, sz);
00433
00434 return victim ? BOUNDED_N(victim, sz) : 0;
00435 }
00436
00437 static Void_t*
00438 #if __STD_C
00439 memalign_starter(size_t align, size_t sz, const Void_t *caller)
00440 #else
00441 memalign_starter(align, sz, caller) size_t align, sz; const Void_t *caller;
00442 #endif
00443 {
00444 Void_t* victim;
00445
00446 victim = _int_memalign(&main_arena, align, sz);
00447
00448 return victim ? BOUNDED_N(victim, sz) : 0;
00449 }
00450
00451 static void
00452 #if __STD_C
00453 free_starter(Void_t* mem, const Void_t *caller)
00454 #else
00455 free_starter(mem, caller) Void_t* mem; const Void_t *caller;
00456 #endif
00457 {
00458 mchunkptr p;
00459
00460 if(!mem) return;
00461 p = mem2chunk(mem);
00462 #if HAVE_MMAP
00463 if (chunk_is_mmapped(p)) {
00464 munmap_chunk(p);
00465 return;
00466 }
00467 #endif
00468 _int_free(&main_arena, mem);
00469 }
00470
00471 # endif
00472 #endif
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 #define MALLOC_STATE_MAGIC 0x444c4541l
00492 #define MALLOC_STATE_VERSION (0*0x100l + 2l)
00493
00494 struct malloc_save_state {
00495 long magic;
00496 long version;
00497 mbinptr av[NBINS * 2 + 2];
00498 char* sbrk_base;
00499 int sbrked_mem_bytes;
00500 unsigned long trim_threshold;
00501 unsigned long top_pad;
00502 unsigned int n_mmaps_max;
00503 unsigned long mmap_threshold;
00504 int check_action;
00505 unsigned long max_sbrked_mem;
00506 unsigned long max_total_mem;
00507 unsigned int n_mmaps;
00508 unsigned int max_n_mmaps;
00509 unsigned long mmapped_mem;
00510 unsigned long max_mmapped_mem;
00511 int using_malloc_checking;
00512 };
00513
00514 Void_t*
00515 public_gET_STATe(void)
00516 {
00517 struct malloc_save_state* ms;
00518 int i;
00519 mbinptr b;
00520
00521 ms = (struct malloc_save_state*)public_mALLOc(sizeof(*ms));
00522 if (!ms)
00523 return 0;
00524 (void)mutex_lock(&main_arena.mutex);
00525 malloc_consolidate(&main_arena);
00526 ms->magic = MALLOC_STATE_MAGIC;
00527 ms->version = MALLOC_STATE_VERSION;
00528 ms->av[0] = 0;
00529 ms->av[1] = 0;
00530 ms->av[2] = top(&main_arena);
00531 ms->av[3] = 0;
00532 for(i=1; i<NBINS; i++) {
00533 b = bin_at(&main_arena, i);
00534 if(first(b) == b)
00535 ms->av[2*i+2] = ms->av[2*i+3] = 0;
00536 else {
00537 ms->av[2*i+2] = first(b);
00538 ms->av[2*i+3] = last(b);
00539 }
00540 }
00541 ms->sbrk_base = mp_.sbrk_base;
00542 ms->sbrked_mem_bytes = main_arena.system_mem;
00543 ms->trim_threshold = mp_.trim_threshold;
00544 ms->top_pad = mp_.top_pad;
00545 ms->n_mmaps_max = mp_.n_mmaps_max;
00546 ms->mmap_threshold = mp_.mmap_threshold;
00547 ms->check_action = check_action;
00548 ms->max_sbrked_mem = main_arena.max_system_mem;
00549 #ifdef NO_THREADS
00550 ms->max_total_mem = mp_.max_total_mem;
00551 #else
00552 ms->max_total_mem = 0;
00553 #endif
00554 ms->n_mmaps = mp_.n_mmaps;
00555 ms->max_n_mmaps = mp_.max_n_mmaps;
00556 ms->mmapped_mem = mp_.mmapped_mem;
00557 ms->max_mmapped_mem = mp_.max_mmapped_mem;
00558 ms->using_malloc_checking = using_malloc_checking;
00559 (void)mutex_unlock(&main_arena.mutex);
00560 return (Void_t*)ms;
00561 }
00562
00563 int
00564 public_sET_STATe(Void_t* msptr)
00565 {
00566 struct malloc_save_state* ms = (struct malloc_save_state*)msptr;
00567 size_t i;
00568 mbinptr b;
00569
00570 disallow_malloc_check = 1;
00571 ptmalloc_init();
00572 if(ms->magic != MALLOC_STATE_MAGIC) return -1;
00573
00574 if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2;
00575 (void)mutex_lock(&main_arena.mutex);
00576
00577 clear_fastchunks(&main_arena);
00578 set_max_fast(&main_arena, DEFAULT_MXFAST);
00579 for (i=0; i<NFASTBINS; ++i)
00580 main_arena.fastbins[i] = 0;
00581 for (i=0; i<BINMAPSIZE; ++i)
00582 main_arena.binmap[i] = 0;
00583 top(&main_arena) = ms->av[2];
00584 main_arena.last_remainder = 0;
00585 for(i=1; i<NBINS; i++) {
00586 b = bin_at(&main_arena, i);
00587 if(ms->av[2*i+2] == 0) {
00588 assert(ms->av[2*i+3] == 0);
00589 first(b) = last(b) = b;
00590 } else {
00591 if(i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
00592 largebin_index(chunksize(ms->av[2*i+3]))==i)) {
00593 first(b) = ms->av[2*i+2];
00594 last(b) = ms->av[2*i+3];
00595
00596 first(b)->bk = b;
00597 last(b)->fd = b;
00598
00599 mark_bin(&main_arena, i);
00600 } else {
00601
00602
00603 first(b) = last(b) = b;
00604 b = unsorted_chunks(&main_arena);
00605 ms->av[2*i+2]->bk = b;
00606 ms->av[2*i+3]->fd = b->fd;
00607 b->fd->bk = ms->av[2*i+3];
00608 b->fd = ms->av[2*i+2];
00609 }
00610 }
00611 }
00612 mp_.sbrk_base = ms->sbrk_base;
00613 main_arena.system_mem = ms->sbrked_mem_bytes;
00614 mp_.trim_threshold = ms->trim_threshold;
00615 mp_.top_pad = ms->top_pad;
00616 mp_.n_mmaps_max = ms->n_mmaps_max;
00617 mp_.mmap_threshold = ms->mmap_threshold;
00618 check_action = ms->check_action;
00619 main_arena.max_system_mem = ms->max_sbrked_mem;
00620 #ifdef NO_THREADS
00621 mp_.max_total_mem = ms->max_total_mem;
00622 #endif
00623 mp_.n_mmaps = ms->n_mmaps;
00624 mp_.max_n_mmaps = ms->max_n_mmaps;
00625 mp_.mmapped_mem = ms->mmapped_mem;
00626 mp_.max_mmapped_mem = ms->max_mmapped_mem;
00627
00628 if (ms->version >= 1) {
00629
00630
00631 if (ms->using_malloc_checking && !using_malloc_checking &&
00632 !disallow_malloc_check)
00633 __malloc_check_init ();
00634 else if (!ms->using_malloc_checking && using_malloc_checking) {
00635 __malloc_hook = 0;
00636 __free_hook = 0;
00637 __realloc_hook = 0;
00638 __memalign_hook = 0;
00639 using_malloc_checking = 0;
00640 }
00641 }
00642 check_malloc_state(&main_arena);
00643
00644 (void)mutex_unlock(&main_arena.mutex);
00645 return 0;
00646 }
00647
00648
00649
00650
00651
00652