1*6c72b531Sjca /* $OpenBSD: alloc.c,v 1.19 2018/01/16 22:52:32 jca Exp $ */
259bf25f9Sespie
359bf25f9Sespie /* Public domain, like most of the rest of ksh */
47cb960a2Sdownsj
57cb960a2Sdownsj /*
67cb960a2Sdownsj * area-based allocation built on malloc/free
77cb960a2Sdownsj */
87cb960a2Sdownsj
9322c3a8aSmmcc #include <stdint.h>
104a010e0cStb #include <stdlib.h>
11b608f594Smmcc
127cb960a2Sdownsj #include "sh.h"
137cb960a2Sdownsj
145c55448cSespie struct link {
155c55448cSespie struct link *prev;
165c55448cSespie struct link *next;
175c55448cSespie };
183b015934Smillert
193b015934Smillert Area *
ainit(Area * ap)205c55448cSespie ainit(Area *ap)
213b015934Smillert {
225c55448cSespie ap->freelist = NULL;
233b015934Smillert return ap;
243b015934Smillert }
253b015934Smillert
263b015934Smillert void
afreeall(Area * ap)275c55448cSespie afreeall(Area *ap)
283b015934Smillert {
295c55448cSespie struct link *l, *l2;
305c55448cSespie
315c55448cSespie for (l = ap->freelist; l != NULL; l = l2) {
325c55448cSespie l2 = l->next;
335c55448cSespie free(l);
345c55448cSespie }
355c55448cSespie ap->freelist = NULL;
363b015934Smillert }
373b015934Smillert
385c55448cSespie #define L2P(l) ( (void *)(((char *)(l)) + sizeof(struct link)) )
395c55448cSespie #define P2L(p) ( (struct link *)(((char *)(p)) - sizeof(struct link)) )
405c55448cSespie
413b015934Smillert void *
alloc(size_t size,Area * ap)425c55448cSespie alloc(size_t size, Area *ap)
433b015934Smillert {
445c55448cSespie struct link *l;
455c55448cSespie
46a6a9e28aSmmcc /* ensure that we don't overflow by allocating space for link */
47a6a9e28aSmmcc if (size > SIZE_MAX - sizeof(struct link))
48*6c72b531Sjca internal_errorf("unable to allocate memory");
49a6a9e28aSmmcc
50e1b6fda6Stb l = malloc(sizeof(struct link) + size);
5108d672a4Smillert if (l == NULL)
52*6c72b531Sjca internal_errorf("unable to allocate memory");
535c55448cSespie l->next = ap->freelist;
545c55448cSespie l->prev = NULL;
555c55448cSespie if (ap->freelist)
565c55448cSespie ap->freelist->prev = l;
575c55448cSespie ap->freelist = l;
585c55448cSespie
595c55448cSespie return L2P(l);
603b015934Smillert }
613b015934Smillert
62322c3a8aSmmcc /*
63322c3a8aSmmcc * Copied from calloc().
64322c3a8aSmmcc *
65322c3a8aSmmcc * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
66322c3a8aSmmcc * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
67322c3a8aSmmcc */
68322c3a8aSmmcc #define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
69322c3a8aSmmcc
70322c3a8aSmmcc void *
areallocarray(void * ptr,size_t nmemb,size_t size,Area * ap)71f05e5426Smmcc areallocarray(void *ptr, size_t nmemb, size_t size, Area *ap)
72322c3a8aSmmcc {
73322c3a8aSmmcc /* condition logic cloned from calloc() */
74322c3a8aSmmcc if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
75322c3a8aSmmcc nmemb > 0 && SIZE_MAX / nmemb < size) {
76*6c72b531Sjca internal_errorf("unable to allocate memory");
77322c3a8aSmmcc }
78322c3a8aSmmcc
79f05e5426Smmcc return aresize(ptr, nmemb * size, ap);
80322c3a8aSmmcc }
81322c3a8aSmmcc
823b015934Smillert void *
aresize(void * ptr,size_t size,Area * ap)835c55448cSespie aresize(void *ptr, size_t size, Area *ap)
843b015934Smillert {
855c55448cSespie struct link *l, *l2, *lprev, *lnext;
865c55448cSespie
875c55448cSespie if (ptr == NULL)
885c55448cSespie return alloc(size, ap);
895c55448cSespie
904f0a1b90Smmcc /* ensure that we don't overflow by allocating space for link */
914f0a1b90Smmcc if (size > SIZE_MAX - sizeof(struct link))
92*6c72b531Sjca internal_errorf("unable to allocate memory");
934f0a1b90Smmcc
945c55448cSespie l = P2L(ptr);
955c55448cSespie lprev = l->prev;
965c55448cSespie lnext = l->next;
975c55448cSespie
982c71ba4cSderaadt l2 = realloc(l, sizeof(struct link) + size);
9908d672a4Smillert if (l2 == NULL)
100*6c72b531Sjca internal_errorf("unable to allocate memory");
1015c55448cSespie if (lprev)
1025c55448cSespie lprev->next = l2;
1035c55448cSespie else
1045c55448cSespie ap->freelist = l2;
1055c55448cSespie if (lnext)
1065c55448cSespie lnext->prev = l2;
10708d672a4Smillert
1085c55448cSespie return L2P(l2);
1095c55448cSespie }
1105c55448cSespie
1115c55448cSespie void
afree(void * ptr,Area * ap)1125c55448cSespie afree(void *ptr, Area *ap)
1135c55448cSespie {
114526c36bdSjca struct link *l;
1155c55448cSespie
1163b015934Smillert if (!ptr)
1175c55448cSespie return;
1185c55448cSespie
1195c55448cSespie l = P2L(ptr);
1205c55448cSespie if (l->prev)
1215c55448cSespie l->prev->next = l->next;
1223b015934Smillert else
1235c55448cSespie ap->freelist = l->next;
1245c55448cSespie if (l->next)
1255c55448cSespie l->next->prev = l->prev;
1263b015934Smillert
1275c55448cSespie free(l);
1287cb960a2Sdownsj }
129