GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/alloc.c Lines: 51 57 89.5 %
Date: 2016-12-06 Branches: 25 36 69.4 %

Line Branch Exec Source
1
/*	$OpenBSD: alloc.c,v 1.15 2016/06/01 10:29:20 espie 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
428110
{
22
428110
	ap->freelist = NULL;
23
428110
	return ap;
24
}
25
26
void
27
afreeall(Area *ap)
28
427188
{
29
	struct link *l, *l2;
30
31
1631240
	for (l = ap->freelist; l != NULL; l = l2) {
32
1204052
		l2 = l->next;
33
1204052
		free(l);
34
	}
35
427188
	ap->freelist = NULL;
36
427188
}
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
3007098
{
44
	struct link *l;
45
46
	/* ensure that we don't overflow by allocating space for link */
47
3007098
	if (size > SIZE_MAX - sizeof(struct link))
48
		internal_errorf(1, "unable to allocate memory");
49
50
3007098
	l = malloc(sizeof(struct link) + size);
51
3007098
	if (l == NULL)
52
		internal_errorf(1, "unable to allocate memory");
53
3007098
	l->next = ap->freelist;
54
3007098
	l->prev = NULL;
55
3007098
	if (ap->freelist)
56
2558416
		ap->freelist->prev = l;
57
3007098
	ap->freelist = l;
58
59
3007098
	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
867150
{
73
	/* condition logic cloned from calloc() */
74

867150
	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
75
	    nmemb > 0 && SIZE_MAX / nmemb < size) {
76
		internal_errorf(1, "unable to allocate memory");
77
	}
78
79
867150
	return aresize(ptr, nmemb * size, ap);
80
}
81
82
void *
83
aresize(void *ptr, size_t size, Area *ap)
84
1539668
{
85
	struct link *l, *l2, *lprev, *lnext;
86
87
1539668
	if (ptr == NULL)
88
597475
		return alloc(size, ap);
89
90
	/* ensure that we don't overflow by allocating space for link */
91
942193
	if (size > SIZE_MAX - sizeof(struct link))
92
		internal_errorf(1, "unable to allocate memory");
93
94
942193
	l = P2L(ptr);
95
942193
	lprev = l->prev;
96
942193
	lnext = l->next;
97
98
942193
	l2 = realloc(l, sizeof(struct link) + size);
99
942193
	if (l2 == NULL)
100
		internal_errorf(1, "unable to allocate memory");
101
942193
	if (lprev)
102
289012
		lprev->next = l2;
103
	else
104
653181
		ap->freelist = l2;
105
942193
	if (lnext)
106
764521
		lnext->prev = l2;
107
108
942193
	return L2P(l2);
109
}
110
111
void
112
afree(void *ptr, Area *ap)
113
1327136
{
114
	struct link *l, *l2;
115
116
1327136
	if (!ptr)
117
239271
		return;
118
119
1087865
	l = P2L(ptr);
120
121
4990882
	for (l2 = ap->freelist; l2 != NULL; l2 = l2->next) {
122
4990882
		if (l == l2)
123
1087865
			break;
124
	}
125
1087865
	if (l2 == NULL)
126
		internal_errorf(1, "afree: %p not present in area %p", ptr, ap);
127
128
1087865
	if (l->prev)
129
454121
		l->prev->next = l->next;
130
	else
131
633744
		ap->freelist = l->next;
132
1087865
	if (l->next)
133
787537
		l->next->prev = l->prev;
134
135
1087865
	free(l);
136
}