1/*- 2 * Copyright (c) 2009, 2010, 2011, 2013, 2014 3 * Thorsten Glaser <tg@mirbsd.org> 4 * 5 * Provided that these terms and disclaimer and all copyright notices 6 * are retained or reproduced in an accompanying document, permission 7 * is granted to deal in this work without restriction, including un- 8 * limited rights to use, publicly perform, distribute, sell, modify, 9 * merge, give away, or sublicence. 10 * 11 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 12 * the utmost extent permitted by applicable law, neither express nor 13 * implied; without malicious intent or gross negligence. In no event 14 * may a licensor, author or contributor be held liable for indirect, 15 * direct, other damage, loss, or other issues arising in any way out 16 * of dealing in the work, even if advised of the possibility of such 17 * damage or existence of a defect, except proven that it results out 18 * of said person's immediate fault when using the work as intended. 19 */ 20 21#include "sh.h" 22 23__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20.2.1 2015/01/25 15:35:47 tg Exp $"); 24 25/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */ 26#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0) 27#define remalloc(p,n) ((p) == NULL ? malloc_osi(n) : realloc_osi((p), (n))) 28#else 29#define remalloc(p,n) realloc_osi((p), (n)) 30#endif 31 32#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % ALLOC_SIZE) 33 34static ALLOC_ITEM *findptr(ALLOC_ITEM **, char *, Area *); 35 36void 37ainit(Area *ap) 38{ 39 /* area pointer is an ALLOC_ITEM, just the head of the list */ 40 ap->next = NULL; 41} 42 43static ALLOC_ITEM * 44findptr(ALLOC_ITEM **lpp, char *ptr, Area *ap) 45{ 46 void *lp; 47 48#ifndef MKSH_SMALL 49 if (ALLOC_ISUNALIGNED(ptr)) 50 goto fail; 51#endif 52 /* get address of ALLOC_ITEM from user item */ 53 /* 54 * note: the alignment of "ptr" to ALLOC_SIZE is checked 55 * above; the "void *" gets us rid of a gcc 2.95 warning 56 */ 57 *lpp = (lp = ptr - ALLOC_SIZE); 58 /* search for allocation item in group list */ 59 while (ap->next != lp) 60 if ((ap = ap->next) == NULL) { 61#ifndef MKSH_SMALL 62 fail: 63#endif 64#ifdef DEBUG 65 internal_warningf("rogue pointer %zX in ap %zX", 66 (size_t)ptr, (size_t)ap); 67 /* try to get a coredump */ 68 abort(); 69#else 70 internal_errorf("rogue pointer %zX", (size_t)ptr); 71#endif 72 } 73 return (ap); 74} 75 76void * 77aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap) 78{ 79 if (notoktomul(fac1, fac2)) 80 internal_errorf(Tintovfl, fac1, '*', fac2); 81 return (aresize(ptr, fac1 * fac2, ap)); 82} 83 84void * 85aresize(void *ptr, size_t numb, Area *ap) 86{ 87 ALLOC_ITEM *lp = NULL; 88 89 /* resizing (true) or newly allocating? */ 90 if (ptr != NULL) { 91 ALLOC_ITEM *pp; 92 93 pp = findptr(&lp, ptr, ap); 94 pp->next = lp->next; 95 } 96 97 if (notoktoadd(numb, ALLOC_SIZE) || 98 (lp = remalloc(lp, numb + ALLOC_SIZE)) == NULL 99#ifndef MKSH_SMALL 100 || ALLOC_ISUNALIGNED(lp) 101#endif 102 ) 103 internal_errorf(Toomem, numb); 104 /* this only works because Area is an ALLOC_ITEM */ 105 lp->next = ap->next; 106 ap->next = lp; 107 /* return user item address */ 108 return ((char *)lp + ALLOC_SIZE); 109} 110 111void 112afree(void *ptr, Area *ap) 113{ 114 if (ptr != NULL) { 115 ALLOC_ITEM *lp, *pp; 116 117 pp = findptr(&lp, ptr, ap); 118 /* unhook */ 119 pp->next = lp->next; 120 /* now free ALLOC_ITEM */ 121 free_osimalloc(lp); 122 } 123} 124 125void 126afreeall(Area *ap) 127{ 128 ALLOC_ITEM *lp; 129 130 /* traverse group (linked list) */ 131 while ((lp = ap->next) != NULL) { 132 /* make next ALLOC_ITEM head of list */ 133 ap->next = lp->next; 134 /* free old head */ 135 free_osimalloc(lp); 136 } 137} 138