GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/alloc.c Lines: 44 49 89.8 %
Date: 2017-11-07 Branches: 19 26 73.1 %

Line Branch Exec Source
1
/*	$OpenBSD: alloc.c,v 1.17 2017/08/15 17:57:57 jca Exp $	*/
2
3
/* Public domain, like most of the rest of ksh */
4
5
/*
6
 * area-based allocation built on malloc/free
7
 */
8
9
#include <stdint.h>
10
#include <stdlib.h>
11
12
#include "sh.h"
13
14
struct link {
15
	struct link *prev;
16
	struct link *next;
17
};
18
19
Area *
20
ainit(Area *ap)
21
{
22
87504114
	ap->freelist = NULL;
23
43752057
	return ap;
24
}
25
26
void
27
afreeall(Area *ap)
28
{
29
	struct link *l, *l2;
30
31
560031533
	for (l = ap->freelist; l != NULL; l = l2) {
32
208611589
		l2 = l->next;
33
208611589
		free(l);
34
	}
35
47602785
	ap->freelist = NULL;
36
47602785
}
37
38
#define L2P(l)	( (void *)(((char *)(l)) + sizeof(struct link)) )
39
#define P2L(p)	( (struct link *)(((char *)(p)) - sizeof(struct link)) )
40
41
void *
42
alloc(size_t size, Area *ap)
43
{
44
	struct link *l;
45
46
	/* ensure that we don't overflow by allocating space for link */
47
928810998
	if (size > SIZE_MAX - sizeof(struct link))
48
		internal_errorf(1, "unable to allocate memory");
49
50
464405499
	l = calloc(1, sizeof(struct link) + size);
51
464405499
	if (l == NULL)
52
		internal_errorf(1, "unable to allocate memory");
53
464405499
	l->next = ap->freelist;
54
464405499
	l->prev = NULL;
55
464405499
	if (ap->freelist)
56
408489245
		ap->freelist->prev = l;
57
464405499
	ap->freelist = l;
58
59
464405499
	return L2P(l);
60
}
61
62
/*
63
 * Copied from calloc().
64
 *
65
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
66
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
67
 */
68
#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
69
70
void *
71
areallocarray(void *ptr, size_t nmemb, size_t size, Area *ap)
72
{
73
	/* condition logic cloned from calloc() */
74

536295951
	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
75
178765317
	    nmemb > 0 && SIZE_MAX / nmemb < size) {
76
		internal_errorf(1, "unable to allocate memory");
77
	}
78
79
178765317
	return aresize(ptr, nmemb * size, ap);
80
}
81
82
void *
83
aresize(void *ptr, size_t size, Area *ap)
84
{
85
	struct link *l, *l2, *lprev, *lnext;
86
87
585543228
	if (ptr == NULL)
88
130495262
		return alloc(size, ap);
89
90
	/* ensure that we don't overflow by allocating space for link */
91
162276352
	if (size > SIZE_MAX - sizeof(struct link))
92
		internal_errorf(1, "unable to allocate memory");
93
94
162276352
	l = P2L(ptr);
95
162276352
	lprev = l->prev;
96
162276352
	lnext = l->next;
97
98
162276352
	l2 = realloc(l, sizeof(struct link) + size);
99
162276352
	if (l2 == NULL)
100
		internal_errorf(1, "unable to allocate memory");
101
324552704
	if (lprev)
102
162276352
		lprev->next = l2;
103
	else
104
162276352
		ap->freelist = l2;
105
162276352
	if (lnext)
106
148954703
		lnext->prev = l2;
107
108
162276352
	return L2P(l2);
109
292771614
}
110
111
void
112
afree(void *ptr, Area *ap)
113
{
114
	struct link *l;
115
116
443043272
	if (!ptr)
117
26998158
		return;
118
119
194523478
	l = P2L(ptr);
120
194523478
	if (l->prev)
121
84941668
		l->prev->next = l->next;
122
	else
123
109581810
		ap->freelist = l->next;
124
194523478
	if (l->next)
125
146739647
		l->next->prev = l->prev;
126
127
194523478
	free(l);
128
416045114
}