19 #define BUILDING_FOR_TOR
28 #ifndef MALLOC_EXTRA_SANITY
29 #undef MALLOC_EXTRA_SANITY
45 #define SOME_JUNK 0xd0
47 #include <sys/types.h>
49 #include <sys/resource.h>
50 #include <sys/param.h>
82 static size_t g_alignment = 0;
84 extern int __libc_enable_secure;
86 #ifndef HAVE_ISSETUGID
87 static int issetugid(
void)
89 if (__libc_enable_secure)
return 1;
90 if (getuid() != geteuid())
return 1;
91 if (getgid() != getegid())
return 1;
98 #define MADV_FREE MADV_DONTNEED
100 static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER;
102 #define _MALLOC_LOCK_INIT() {;}
103 #define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
104 #define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}
106 #if defined(__sparc__) || defined(__alpha__)
107 #define malloc_pageshift 13U
109 #if defined(__ia64__)
110 #define malloc_pageshift 14U
113 #ifndef malloc_pageshift
114 #define malloc_pageshift (PGSHIFT)
133 #define MALLOC_BITS (int)((NBBY * sizeof(u_long)))
149 #define MALLOC_NOT_MINE ((struct pginfo*) 0)
150 #define MALLOC_FREE ((struct pginfo*) 1)
151 #define MALLOC_FIRST ((struct pginfo*) 2)
152 #define MALLOC_FOLLOW ((struct pginfo*) 3)
153 #define MALLOC_MAGIC ((struct pginfo*) 4)
155 #ifndef malloc_minsize
156 #define malloc_minsize 16UL
159 #if !defined(malloc_pagesize)
160 #define malloc_pagesize (1UL<<malloc_pageshift)
163 #if ((1UL<<malloc_pageshift) != malloc_pagesize)
164 #error "(1UL<<malloc_pageshift) != malloc_pagesize"
167 #ifndef malloc_maxsize
168 #define malloc_maxsize ((malloc_pagesize)>>1)
172 #define malloc_pagemask ((malloc_pagesize)-1)
174 #define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
175 #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
176 #define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
179 static unsigned int malloc_started;
182 static unsigned int malloc_cache = 16;
191 static struct pdinfo *last_dir;
192 static struct pdinfo *prev_dir;
194 static size_t pdi_off;
195 static u_long pdi_mod;
196 #define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
197 #define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
198 #define PI_IDX(index) ((index) / pdi_mod)
199 #define PI_OFF(index) ((index) % pdi_mod)
202 static u_long last_index;
205 static struct pginfo **page_dir;
208 static struct pgfree free_list;
211 static int malloc_abort = 2;
218 static int malloc_stats;
222 static int malloc_silent;
225 static int malloc_realloc;
228 static int malloc_freeprot;
231 static size_t malloc_guard = 0;
232 static size_t malloc_guarded;
234 static int malloc_ptrguard;
236 static int malloc_hint = 1;
239 static int malloc_xmalloc;
242 static int malloc_zero;
245 static int malloc_junk;
249 static int malloc_utrace;
257 void utrace(
struct ut *,
int);
259 #define UTRACE(a, b, c) \
261 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
263 #define UTRACE(a,b,c)
267 static int malloc_active;
270 static size_t malloc_used;
273 static caddr_t malloc_brk;
279 char *malloc_options;
282 static const char *malloc_func;
285 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
291 static void *imalloc(
size_t size);
292 static void ifree(
void *ptr);
293 static void *irealloc(
void *ptr,
size_t size);
294 static void *malloc_bytes(
size_t size);
295 void *memalign(
size_t boundary,
size_t size);
296 size_t malloc_good_size(
size_t size);
302 pdir_lookup(u_long index,
struct pdinfo ** pdi)
305 u_long pidx = PI_IDX(index);
307 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
309 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
311 else if (last_dir != NULL && prev_dir != NULL) {
312 if ((PD_IDX(last_dir->dirnum) > pidx) ?
313 (PD_IDX(last_dir->dirnum) - pidx) :
314 (pidx - PD_IDX(last_dir->dirnum))
315 < (PD_IDX(prev_dir->dirnum) > pidx) ?
316 (PD_IDX(prev_dir->dirnum) - pidx) :
317 (pidx - PD_IDX(prev_dir->dirnum)))
322 if (PD_IDX((*pdi)->dirnum) > pidx) {
323 for (spi = (*pdi)->prev;
324 spi != NULL && PD_IDX(spi->dirnum) > pidx;
330 for (spi = (*pdi)->next;
331 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
335 *pdi = (
struct pdinfo *) ((caddr_t) page_dir + pdi_off);
337 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
342 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
343 (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
357 pi = (
struct pdinfo *) ((caddr_t) pd + pdi_off);
360 for (j = 0; j <= last_index;) {
361 snprintf(buf,
sizeof buf,
"%08lx %5lu ", j << malloc_pageshift, j);
362 write(fd, buf, strlen(buf));
363 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
364 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
366 if ((pi = pi->next) == NULL ||
367 PD_IDX(pi->dirnum) != PI_IDX(j))
374 snprintf(buf,
sizeof buf,
".. %5lu not mine\n", j);
375 write(fd, buf, strlen(buf));
376 }
else if (pd[PI_OFF(j)] == MALLOC_FREE) {
377 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
379 if ((pi = pi->next) == NULL ||
380 PD_IDX(pi->dirnum) != PI_IDX(j))
387 snprintf(buf,
sizeof buf,
".. %5lu free\n", j);
388 write(fd, buf, strlen(buf));
389 }
else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
390 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
392 if ((pi = pi->next) == NULL ||
393 PD_IDX(pi->dirnum) != PI_IDX(j))
400 snprintf(buf,
sizeof buf,
".. %5lu in use\n", j);
401 write(fd, buf, strlen(buf));
402 }
else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
403 snprintf(buf,
sizeof buf,
"(%p)\n", pd[PI_OFF(j)]);
404 write(fd, buf, strlen(buf));
406 snprintf(buf,
sizeof buf,
"%p %d (of %d) x %d @ %p --> %p\n",
407 pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
408 pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
409 pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
410 write(fd, buf, strlen(buf));
413 if ((pi = pi->next) == NULL)
416 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
420 for (pf = free_list.next; pf; pf = pf->next) {
421 snprintf(buf,
sizeof buf,
"Free: @%p [%p...%p[ %ld ->%p <-%p\n",
422 pf, pf->page, (
char *)pf->page + pf->size,
423 pf->size, pf->prev, pf->next);
424 write(fd, buf, strlen(buf));
425 if (pf == pf->next) {
426 snprintf(buf,
sizeof buf,
"Free_list loops\n");
427 write(fd, buf, strlen(buf));
433 snprintf(buf,
sizeof buf,
"Minsize\t%lu\n", malloc_minsize);
434 write(fd, buf, strlen(buf));
435 snprintf(buf,
sizeof buf,
"Maxsize\t%lu\n", malloc_maxsize);
436 write(fd, buf, strlen(buf));
437 snprintf(buf,
sizeof buf,
"Pagesize\t%lu\n", malloc_pagesize);
438 write(fd, buf, strlen(buf));
439 snprintf(buf,
sizeof buf,
"Pageshift\t%u\n", malloc_pageshift);
440 write(fd, buf, strlen(buf));
441 snprintf(buf,
sizeof buf,
"In use\t%lu\n", (u_long) malloc_used);
442 write(fd, buf, strlen(buf));
443 snprintf(buf,
sizeof buf,
"Guarded\t%lu\n", (u_long) malloc_guarded);
444 write(fd, buf, strlen(buf));
448 extern char *__progname;
451 wrterror(
const char *p)
453 #ifndef BUILDING_FOR_TOR
454 const char *q =
" error: ";
457 iov[0].iov_base = __progname;
458 iov[0].iov_len = strlen(__progname);
459 iov[1].iov_base = (
char*)malloc_func;
460 iov[1].iov_len = strlen(malloc_func);
461 iov[2].iov_base = (
char*)q;
462 iov[2].iov_len = strlen(q);
463 iov[3].iov_base = (
char*)p;
464 iov[3].iov_len = strlen(p);
465 iov[4].iov_base = (
char*)
"\n";
467 writev(STDERR_FILENO, iov, 5);
474 malloc_dump(STDERR_FILENO);
482 wrtwarning(
const char *p)
484 #ifndef BUILDING_FOR_TOR
485 const char *q =
" warning: ";
491 else if (malloc_silent)
494 #ifndef BUILDING_FOR_TOR
495 iov[0].iov_base = __progname;
496 iov[0].iov_len = strlen(__progname);
497 iov[1].iov_base = (
char*)malloc_func;
498 iov[1].iov_len = strlen(malloc_func);
499 iov[2].iov_base = (
char*)q;
500 iov[2].iov_len = strlen(q);
501 iov[3].iov_base = (
char*)p;
502 iov[3].iov_len = strlen(p);
503 iov[4].iov_base = (
char*)
"\n";
506 (void) writev(STDERR_FILENO, iov, 5);
516 char *q =
"malloc() warning: Couldn't dump stats\n";
517 int save_errno = errno, fd;
519 fd = open(
"malloc.out", O_RDWR|O_APPEND);
524 write(STDERR_FILENO, q, strlen(q));
533 static void *MMAP_A(
size_t pages,
size_t alignment)
536 size_t first_size, rest, begin, end;
537 if (pages%malloc_pagesize != 0)
538 pages = pages - pages%malloc_pagesize + malloc_pagesize;
539 first_size = pages + alignment - malloc_pagesize;
540 p = MMAP(first_size);
541 rest = ((size_t)p) % alignment;
542 j = (rest == 0) ? p : (
void*) ((size_t)p + alignment - rest);
543 begin = (size_t)j - (
size_t)p;
544 if (begin != 0) munmap(p, begin);
545 end = (size_t)p + first_size - ((
size_t)j + pages);
546 if(end != 0) munmap( (
void*) ((
size_t)j + pages), end);
556 map_pages(
size_t pages)
560 u_long idx, pidx, lidx;
561 caddr_t result, tail;
562 u_long index, lindex;
563 void *pdregion = NULL;
566 pages <<= malloc_pageshift;
568 result = MMAP(pages + malloc_guard);
570 result = MMAP_A(pages + malloc_guard, g_alignment);
572 if (result == MAP_FAILED) {
573 #ifdef MALLOC_EXTRA_SANITY
574 wrtwarning(
"(ES): map_pages fails");
579 index = ptr2index(result);
580 tail = result + pages + malloc_guard;
581 lindex = ptr2index(tail) - 1;
583 mprotect(result + pages, malloc_guard, PROT_NONE);
585 pidx = PI_IDX(index);
586 lidx = PI_IDX(lindex);
588 if (tail > malloc_brk) {
596 if (pdir_lookup(index, &pi) != 0)
600 pdregion = MMAP(malloc_pagesize * dirs);
601 if (pdregion == MAP_FAILED) {
602 munmap(result, tail - result);
603 #ifdef MALLOC_EXTRA_SANITY
604 wrtwarning(
"(ES): map_pages fails");
612 for (idx = pidx, spi = pi; idx <= lidx; idx++) {
613 if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
614 pd = (
struct pginfo **)((
char *)pdregion +
615 cnt * malloc_pagesize);
617 memset(pd, 0, malloc_pagesize);
618 pi = (
struct pdinfo *) ((caddr_t) pd + pdi_off);
621 pi->next = spi->next;
622 pi->dirnum = idx * (malloc_pagesize /
625 if (spi->next != NULL)
626 spi->next->prev = pi;
629 if (idx > pidx && idx < lidx) {
630 pi->dirnum += pdi_mod;
631 }
else if (idx == pidx) {
633 pi->dirnum += (u_long)(tail - result) >>
636 pi->dirnum += pdi_mod - PI_OFF(index);
639 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
641 #ifdef MALLOC_EXTRA_SANITY
642 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
643 wrterror(
"(ES): pages directory overflow");
648 if (idx == pidx && pi != last_dir) {
655 #ifdef MALLOC_EXTRA_SANITY
657 wrtwarning(
"(ES): cnt > dirs");
660 munmap((
char *)pdregion + cnt * malloc_pagesize,
661 (dirs - cnt) * malloc_pagesize);
673 int i, j, save_errno = errno;
677 #ifdef MALLOC_EXTRA_SANITY
681 for (i = 0; i < 3; i++) {
684 j = (int) readlink(
"/etc/malloc.conf", b,
sizeof b - 1);
691 if (issetugid() == 0)
692 p = getenv(
"MALLOC_OPTIONS");
703 for (; p != NULL && *p !=
'\0'; p++) {
735 malloc_guard = malloc_pagesize;
790 wrtwarning(
"unknown char in MALLOC_OPTIONS");
807 if (malloc_stats && (atexit(malloc_exit) == -1))
808 wrtwarning(
"atexit(2) failed."
809 " Will not be able to dump malloc stats on exit");
812 if (malloc_pagesize != getpagesize()) {
813 wrterror(
"malloc() replacement compiled with a different "
814 "page size from what we're running with. Failing.");
820 page_dir = (
struct pginfo **)MMAP(malloc_pagesize);
822 if (page_dir == MAP_FAILED) {
823 wrterror(
"mmap(2) failed, check limits");
827 pdi_off = (malloc_pagesize -
sizeof(
struct pdinfo)) & ~(malloc_minsize - 1);
828 pdi_mod = pdi_off /
sizeof(
struct pginfo *);
830 last_dir = (
struct pdinfo *) ((caddr_t) page_dir + pdi_off);
831 last_dir->base = page_dir;
832 last_dir->prev = last_dir->next = NULL;
833 last_dir->dirnum = malloc_pageshift;
841 malloc_cache <<= malloc_pageshift;
849 malloc_pages(
size_t size)
851 void *p, *delay_free = NULL, *tp;
858 size = pageround(size) + malloc_guard;
863 for (pf = free_list.next; pf; pf = pf->next) {
865 #ifdef MALLOC_EXTRA_SANITY
866 if (pf->size & malloc_pagemask) {
867 wrterror(
"(ES): junk length entry on free_list");
872 wrterror(
"(ES): zero length entry on free_list");
876 if (pf->page > (pf->page + pf->size)) {
877 wrterror(
"(ES): sick entry on free_list");
881 if ((pi = pf->pdir) == NULL) {
882 wrterror(
"(ES): invalid page directory on free-list");
886 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
887 wrterror(
"(ES): directory index mismatch on free-list");
892 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
893 wrterror(
"(ES): non-free first page on free-list");
897 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
898 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
901 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
902 wrterror(
"(ES): last page not referenced in page directory");
907 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
908 wrterror(
"(ES): non-free last page on free-list");
917 if (pf->size == size) {
920 if (pf->next != NULL)
921 pf->next->prev = pf->prev;
922 pf->prev->next = pf->next;
927 pf->page = (
char *) pf->page + size;
929 pidx = PI_IDX(ptr2index(pf->page));
930 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
933 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
934 wrterror(
"(ES): hole in directories");
944 size -= malloc_guard;
946 #ifdef MALLOC_EXTRA_SANITY
947 if (p != NULL && pi != NULL) {
948 pidx = PD_IDX(pi->dirnum);
951 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
952 wrterror(
"(ES): allocated non-free page on free-list");
958 if (p != NULL && (malloc_guard || malloc_freeprot))
959 mprotect(p, size, PROT_READ | PROT_WRITE);
961 size >>= malloc_pageshift;
968 index = ptr2index(p);
969 pidx = PI_IDX(index);
970 pdir_lookup(index, &pi);
971 #ifdef MALLOC_EXTRA_SANITY
972 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
973 wrterror(
"(ES): mapped pages not found in directory");
978 if (pi != last_dir) {
983 pd[PI_OFF(index)] = MALLOC_FIRST;
985 for (i = 1; i < size; i++) {
986 if (!PI_OFF(index + i)) {
989 #ifdef MALLOC_EXTRA_SANITY
990 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
991 wrterror(
"(ES): hole in mapped pages directory");
998 pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
1001 if (!PI_OFF(index + i)) {
1004 #ifdef MALLOC_EXTRA_SANITY
1005 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1006 wrterror(
"(ES): hole in mapped pages directory");
1013 pd[PI_OFF(index + i)] = MALLOC_FIRST;
1016 malloc_used += size << malloc_pageshift;
1017 malloc_guarded += malloc_guard;
1020 memset(p, SOME_JUNK, size << malloc_pageshift);
1035 static __inline__
int
1036 malloc_make_chunks(
int bits)
1040 #ifdef MALLOC_EXTRA_SANITY
1048 pp = malloc_pages((
size_t) malloc_pagesize);
1053 l =
sizeof *bp -
sizeof(u_long);
1054 l +=
sizeof(u_long) *
1055 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);
1065 if (bits != 0 && (1UL << (bits)) <= l + l) {
1066 bp = (
struct pginfo *) pp;
1068 bp = (
struct pginfo *) imalloc(l);
1079 i = malloc_minsize - 1;
1082 bp->total = bp->free = malloc_pagesize >> bp->shift;
1085 k = mprotect(pp, malloc_pagesize, PROT_NONE);
1092 bp->size = (1UL << bits);
1094 bp->total = bp->free = malloc_pagesize >> bits;
1103 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
1104 bp->bits[i / MALLOC_BITS] = ~0UL;
1107 bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1110 if (bp == bp->page) {
1112 for (i = 0; k > 0; i++) {
1113 bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS));
1121 pdir_lookup(ptr2index(pp), &pi);
1122 #ifdef MALLOC_EXTRA_SANITY
1123 pidx = PI_IDX(ptr2index(pp));
1124 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1125 wrterror(
"(ES): mapped pages not found in directory");
1130 if (pi != last_dir) {
1131 prev_dir = last_dir;
1135 pd[PI_OFF(ptr2index(pp))] = bp;
1137 bp->next = page_dir[bits];
1138 page_dir[bits] = bp;
1148 malloc_bytes(
size_t size)
1157 if (size != 0 && size < malloc_minsize)
1158 size = malloc_minsize;
1172 if (page_dir[j] == NULL && !malloc_make_chunks(j))
1178 for (lp = bp->bits; !*lp; lp++);
1183 while (!(*lp & u)) {
1191 i = rand() % bp->free;
1195 if (k >= MALLOC_BITS) {
1200 #ifdef MALLOC_EXTRA_SANITY
1201 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1202 wrterror(
"chunk overflow");
1215 page_dir[j] = bp->next;
1219 k += (lp - bp->bits) * MALLOC_BITS;
1222 if (malloc_junk && bp->size != 0)
1223 memset((
char *)bp->page + k, SOME_JUNK, (
size_t)bp->size);
1225 return ((u_char *) bp->page + k);
1231 #define PTR_GAP (malloc_pagesize - sizeof(void *))
1232 #define PTR_SIZE (sizeof(void *))
1233 #define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP)
1239 imalloc(
size_t size)
1244 if (!malloc_started)
1252 px = malloc_bytes(
sizeof *px);
1254 if (malloc_ptrguard && size == PTR_SIZE) {
1256 size = malloc_pagesize;
1258 if (size > SIZE_MAX - malloc_pagesize) {
1261 }
else if (size <= malloc_maxsize)
1262 result = malloc_bytes(size);
1264 result = malloc_pages(size);
1266 if (malloc_abort == 1 && result == NULL)
1267 wrterror(
"allocation failed");
1269 if (malloc_zero && result != NULL)
1270 memset(result, 0, size);
1272 if (result && ptralloc)
1273 return ((
char *) result + PTR_GAP);
1281 irealloc(
void *ptr,
size_t size)
1289 #ifdef MALLOC_EXTRA_SANITY
1296 if (!malloc_started) {
1297 wrtwarning(
"malloc() has never been called");
1300 if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
1301 if (size <= PTR_SIZE)
1306 memcpy(p, ptr, PTR_SIZE);
1310 index = ptr2index(ptr);
1312 if (index < malloc_pageshift) {
1313 wrtwarning(
"junk pointer, too low to make sense");
1316 if (index > last_index) {
1317 wrtwarning(
"junk pointer, too high to make sense");
1320 pdir_lookup(index, &pi);
1321 #ifdef MALLOC_EXTRA_SANITY
1322 pidx = PI_IDX(index);
1323 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1324 wrterror(
"(ES): mapped pages not found in directory");
1329 if (pi != last_dir) {
1330 prev_dir = last_dir;
1334 mp = &pd[PI_OFF(index)];
1336 if (*mp == MALLOC_FIRST) {
1339 if ((u_long) ptr & malloc_pagemask) {
1340 wrtwarning(
"modified (page-) pointer");
1347 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1352 for (osize = malloc_pagesize;
1353 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1354 osize += malloc_pagesize;
1357 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1364 if (!malloc_realloc && size <= osize &&
1365 size > osize - malloc_pagesize) {
1367 memset((
char *)ptr + size, SOME_JUNK, osize - size);
1370 }
else if (*mp >= MALLOC_MAGIC) {
1373 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
1374 wrtwarning(
"modified (chunk-) pointer");
1378 i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift;
1381 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1382 wrtwarning(
"chunk is already free");
1385 osize = (*mp)->size;
1387 if (!malloc_realloc && size <= osize &&
1388 (size > osize / 2 || osize == malloc_minsize)) {
1390 memset((
char *) ptr + size, SOME_JUNK, osize - size);
1394 wrtwarning(
"irealloc: pointer to wrong page");
1403 if (osize != 0 && size != 0) {
1405 memcpy(p, ptr, osize);
1407 memcpy(p, ptr, size);
1417 static __inline__
void
1418 free_pages(
void *ptr, u_long index,
struct pginfo * info)
1420 u_long i, pidx, lidx;
1421 size_t l, cachesize = 0;
1424 struct pgfree *pf, *pt = NULL;
1427 if (info == MALLOC_FREE) {
1428 wrtwarning(
"page is already free");
1431 if (info != MALLOC_FIRST) {
1432 wrtwarning(
"free_pages: pointer to wrong page");
1435 if ((u_long) ptr & malloc_pagemask) {
1436 wrtwarning(
"modified (page-) pointer");
1440 pidx = PI_IDX(index);
1441 pdir_lookup(index, &pi);
1442 #ifdef MALLOC_EXTRA_SANITY
1443 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1444 wrterror(
"(ES): mapped pages not found in directory");
1453 pd[PI_OFF(index)] = MALLOC_FREE;
1455 if (!PI_OFF(index + i)) {
1457 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
1462 while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) {
1463 pd[PI_OFF(index + i)] = MALLOC_FREE;
1465 if (!PI_OFF(index + i)) {
1466 if ((pi = pi->next) == NULL ||
1467 PD_IDX(pi->dirnum) != PI_IDX(index + i))
1474 l = i << malloc_pageshift;
1477 memset(ptr, SOME_JUNK, l);
1480 malloc_guarded -= malloc_guard;
1482 #ifdef MALLOC_EXTRA_SANITY
1483 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
1484 wrterror(
"(ES): hole in mapped pages directory");
1489 pd[PI_OFF(index + i)] = MALLOC_FREE;
1492 tail = (caddr_t)ptr + l;
1495 madvise(ptr, l, MADV_FREE);
1497 if (malloc_freeprot)
1498 mprotect(ptr, l, PROT_NONE);
1501 if (px == NULL && (px = malloc_bytes(
sizeof *px)) == NULL)
1507 if (free_list.next == NULL) {
1510 px->prev = &free_list;
1511 free_list.next = px;
1521 for (pf = free_list.next;
1522 (caddr_t)ptr > ((caddr_t)pf->page + pf->size)
1523 && pf->next != NULL;
1525 cachesize += pf->size;
1530 cachesize += pt->size;
1534 if ((caddr_t)pf->page > tail) {
1537 px->prev = pf->prev;
1539 px->prev->next = px;
1542 }
else if (((caddr_t)pf->page + pf->size) == ptr) {
1544 cachesize -= pf->size;
1546 if (pf->next != NULL &&
1547 pf->next->page == ((caddr_t)pf->page + pf->size)) {
1550 pf->size += pt->size;
1551 pf->next = pt->next;
1552 if (pf->next != NULL)
1553 pf->next->prev = pf;
1555 }
else if (pf->page == tail) {
1557 cachesize -= pf->size;
1561 }
else if (pf->next == NULL) {
1569 wrterror(
"freelist is destroyed");
1575 if (pf->pdir != last_dir) {
1576 prev_dir = last_dir;
1577 last_dir = pf->pdir;
1581 if (pf->size > (malloc_cache - cachesize)) {
1587 if (munmap((
char *) pf->page + (malloc_cache - cachesize),
1588 pf->size - (malloc_cache - cachesize)) != 0)
1590 tail = (caddr_t)pf->page + pf->size;
1591 lidx = ptr2index(tail) - 1;
1592 pf->size = malloc_cache - cachesize;
1594 index = ptr2index((caddr_t)pf->page + pf->size);
1596 pidx = PI_IDX(index);
1597 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1600 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
1605 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1608 for (i = index; i <= lidx;) {
1609 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1610 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1611 #ifdef MALLOC_EXTRA_SANITY
1612 if (!PD_OFF(pi->dirnum)) {
1613 wrterror(
"(ES): pages directory underflow");
1620 #ifdef MALLOC_EXTRA_SANITY
1622 wrtwarning(
"(ES): page already unmapped");
1630 if (!PD_OFF(pi->dirnum)) {
1634 if (pi->prev != NULL)
1635 pi->prev->next = pi->next;
1636 if (pi->next != NULL)
1637 pi->next->prev = pi->prev;
1639 munmap(pd, malloc_pagesize);
1643 PD_IDX(pi->dirnum) != PI_IDX(i))
1648 if (pi && !PD_OFF(pi->dirnum)) {
1653 if (pi->prev != NULL)
1654 pi->prev->next = pi->next;
1655 if (pi->next != NULL)
1656 pi->next->prev = pi->prev;
1658 munmap(pd, malloc_pagesize);
1661 if (pi == NULL && malloc_brk == tail) {
1663 last_index = index - 1;
1664 malloc_brk = index2ptr(index);
1668 if (pf->size == 0) {
1671 if ((px = pf->prev) != &free_list) {
1672 if (pi == NULL && last_index == (index - 1)) {
1678 if (PD_IDX(spi->dirnum) < pidx)
1680 ((PD_IDX(spi->dirnum) + 1) *
1682 for (pi = spi, i = index;
1683 pd[PI_OFF(i)] == MALLOC_NOT_MINE;
1685 #ifdef MALLOC_EXTRA_SANITY
1688 if (pi == NULL || i == 0)
1691 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
1697 malloc_brk = index2ptr(i + 1);
1701 if ((px->next = pf->next) != NULL)
1702 px->next->prev = px;
1704 if ((free_list.next = pf->next) != NULL)
1705 free_list.next->prev = &free_list;
1708 last_dir = prev_dir;
1722 static __inline__
void
1723 free_bytes(
void *ptr, u_long index,
struct pginfo * info)
1725 struct pginfo **mp, **pd;
1727 #ifdef MALLOC_EXTRA_SANITY
1735 i = ((u_long) ptr & malloc_pagemask) >> info->shift;
1737 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
1738 wrtwarning(
"modified (chunk-) pointer");
1741 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1742 wrtwarning(
"chunk is already free");
1745 if (malloc_junk && info->size != 0)
1746 memset(ptr, SOME_JUNK, (
size_t)info->size);
1748 info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1751 if (info->size != 0)
1752 mp = page_dir + info->shift;
1756 if (info->free == 1) {
1760 while (*mp != NULL && (*mp)->next != NULL &&
1761 (*mp)->next->page < info->page)
1767 if (info->free != info->total)
1771 while (*mp != info) {
1772 mp = &((*mp)->next);
1773 #ifdef MALLOC_EXTRA_SANITY
1775 wrterror(
"(ES): Not on queue");
1784 pdir_lookup(ptr2index(info->page), &pi);
1785 #ifdef MALLOC_EXTRA_SANITY
1786 pidx = PI_IDX(ptr2index(info->page));
1787 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1788 wrterror(
"(ES): mapped pages not found in directory");
1793 if (pi != last_dir) {
1794 prev_dir = last_dir;
1798 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1801 if (info->size == 0)
1802 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);
1805 if (vp != (
void *) info)
1813 struct pginfo *info, **pd;
1815 #ifdef MALLOC_EXTRA_SANITY
1820 if (!malloc_started) {
1821 wrtwarning(
"malloc() has never been called");
1828 if (malloc_ptrguard && PTR_ALIGNED(ptr))
1829 ptr = (
char *) ptr - PTR_GAP;
1831 index = ptr2index(ptr);
1833 if (index < malloc_pageshift) {
1835 wrtwarning(
"ifree: junk pointer, too low to make sense");
1838 if (index > last_index) {
1840 wrtwarning(
"ifree: junk pointer, too high to make sense");
1843 pdir_lookup(index, &pi);
1844 #ifdef MALLOC_EXTRA_SANITY
1845 pidx = PI_IDX(index);
1846 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1847 wrterror(
"(ES): mapped pages not found in directory");
1852 if (pi != last_dir) {
1853 prev_dir = last_dir;
1857 info = pd[PI_OFF(index)];
1859 if (info < MALLOC_MAGIC)
1860 free_pages(ptr, index, info);
1862 free_bytes(ptr, index, info);
1866 px = malloc_bytes(
sizeof *px);
1877 malloc_recurse(
void)
1883 wrtwarning(
"recursive call");
1900 malloc_func =
" in malloc():";
1901 if (malloc_active++) {
1910 if (malloc_xmalloc && r == NULL) {
1911 wrterror(
"out of memory");
1925 malloc_func =
" in free():";
1926 if (malloc_active++) {
1938 realloc(
void *ptr,
size_t size)
1943 malloc_func =
" in realloc():";
1944 if (malloc_active++) {
1952 r = irealloc(ptr, size);
1954 UTRACE(ptr, size, r);
1957 if (malloc_xmalloc && r == NULL) {
1958 wrterror(
"out of memory");
1965 calloc(
size_t num,
size_t size)
1969 if (num && SIZE_MAX / num < size) {
1970 fprintf(stderr,
"OOOOPS");
1981 #ifndef BUILDING_FOR_TOR
1982 static int ispowerof2 (
size_t a) {
1984 for (b = 1ULL << (
sizeof(
size_t)*NBBY - 1); b > 1; b >>= 1)
1991 #ifndef BUILDING_FOR_TOR
1992 int posix_memalign(
void **memptr,
size_t alignment,
size_t size)
1996 if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0))
return EINVAL;
1997 if (!ispowerof2(alignment))
return EINVAL;
1998 if (alignment < malloc_minsize) alignment = malloc_minsize;
1999 max = alignment > size ? alignment : size;
2000 if (alignment <= malloc_pagesize)
2005 g_alignment = alignment;
2011 if (!r)
return ENOMEM;
2015 void *memalign(
size_t boundary,
size_t size)
2018 posix_memalign(&r, boundary, size);
2022 void *valloc(
size_t size)
2025 posix_memalign(&r, malloc_pagesize, size);
2030 size_t malloc_good_size(
size_t size)
2034 }
else if (size <= malloc_maxsize) {
2043 return ((
size_t)1) << j;
2045 return pageround(size);
Integer definitions used throughout Tor.