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

Line Branch Exec Source
1
/*	$OpenBSD: alloc.c,v 1.18 2017/11/02 06:55:35 tb 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
27515878
	ap->freelist = NULL;
23
13757939
	return ap;
24
}
25
26
void
27
afreeall(Area *ap)
28
{
29
	struct link *l, *l2;
30
31
156066498
	for (l = ap->freelist; l != NULL; l = l2) {
32
56563581
		l2 = l->next;
33
56563581
		free(l);
34
	}
35
14313112
	ap->freelist = NULL;
36
14313112
}
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
259328748
	if (size > SIZE_MAX - sizeof(struct link))
48
		internal_errorf(1, "unable to allocate memory");
49
50
129664374
	l = malloc(sizeof(struct link) + size);
51
129664374
	if (l == NULL)
52
		internal_errorf(1, "unable to allocate memory");
53
129664374
	l->next = ap->freelist;
54
129664374
	l->prev = NULL;
55
129664374
	if (ap->freelist)
56
112477077
		ap->freelist->prev = l;
57
129664374
	ap->freelist = l;
58
59
129664374
	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

115864551
	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
75
38621517
	    nmemb > 0 && SIZE_MAX / nmemb < size) {
76
		internal_errorf(1, "unable to allocate memory");
77
	}
78
79
38621517
	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
134715068
	if (ptr == NULL)
88
26483825
		return alloc(size, ap);
89
90
	/* ensure that we don't overflow by allocating space for link */
91
40873709
	if (size > SIZE_MAX - sizeof(struct link))
92
		internal_errorf(1, "unable to allocate memory");
93
94
40873709
	l = P2L(ptr);
95
40873709
	lprev = l->prev;
96
40873709
	lnext = l->next;
97
98
40873709
	l2 = realloc(l, sizeof(struct link) + size);
99
40873709
	if (l2 == NULL)
100
		internal_errorf(1, "unable to allocate memory");
101
81747418
	if (lprev)
102
40873709
		lprev->next = l2;
103
	else
104
40873709
		ap->freelist = l2;
105
40873709
	if (lnext)
106
37285239
		lnext->prev = l2;
107
108
40873709
	return L2P(l2);
109
67357534
}
110
111
void
112
afree(void *ptr, Area *ap)
113
{
114
	struct link *l;
115
116
115368698
	if (!ptr)
117
11307332
		return;
118
119
46377017
	l = P2L(ptr);
120
46377017
	if (l->prev)
121
18245654
		l->prev->next = l->next;
122
	else
123
28131363
		ap->freelist = l->next;
124
46377017
	if (l->next)
125
32372043
		l->next->prev = l->prev;
126
127
46377017
	free(l);
128
104061366
}