summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/Makefile.inc3
-rw-r--r--src/lib/libc/stdlib/malloc.370
-rw-r--r--src/lib/libc/stdlib/recallocarray.c81
3 files changed, 147 insertions, 7 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 3489e44021..36b5869adb 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.61 2016/08/14 23:18:03 guenther Exp $ 1# $OpenBSD: Makefile.inc,v 1.62 2017/03/06 18:44:21 otto Exp $
2 2
3# stdlib sources 3# stdlib sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib
@@ -7,6 +7,7 @@ SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ 7 exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c insque.c \ 8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c insque.c \
9 l64a.c llabs.c lldiv.c lsearch.c malloc.c reallocarray.c \ 9 l64a.c llabs.c lldiv.c lsearch.c malloc.c reallocarray.c \
10 recallocarray.c \
10 merge.c posix_pty.c qsort.c radixsort.c rand.c random.c \ 11 merge.c posix_pty.c qsort.c radixsort.c rand.c random.c \
11 realpath.c remque.c setenv.c strtoimax.c \ 12 realpath.c remque.c setenv.c strtoimax.c \
12 strtol.c strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c \ 13 strtol.c strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c \
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 1f80c3529e..66de428cb0 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -30,9 +30,9 @@
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $OpenBSD: malloc.3,v 1.101 2017/02/12 10:46:09 otto Exp $ 33.\" $OpenBSD: malloc.3,v 1.102 2017/03/06 18:44:21 otto Exp $
34.\" 34.\"
35.Dd $Mdocdate: February 12 2017 $ 35.Dd $Mdocdate: March 6 2017 $
36.Dt MALLOC 3 36.Dt MALLOC 3
37.Os 37.Os
38.Sh NAME 38.Sh NAME
@@ -51,6 +51,8 @@
51.Ft void * 51.Ft void *
52.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size" 52.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
53.Ft void * 53.Ft void *
54.Fn recallocarray "void *ptr" "size_t oldnmemb" "size_t nmemb" "size_t size"
55.Ft void *
54.Fn realloc "void *ptr" "size_t size" 56.Fn realloc "void *ptr" "size_t size"
55.Ft void 57.Ft void
56.Fn free "void *ptr" 58.Fn free "void *ptr"
@@ -113,6 +115,33 @@ and checks for integer overflow in the calculation
113.Fa size . 115.Fa size .
114.Pp 116.Pp
115The 117The
118.Fn recallocarray
119function is similar to
120.Fn reallocarray
121except that it takes care of clearing newly allocated and freed memory.
122If
123.Fa ptr
124is a
125.Dv NULL
126pointer,
127.Fa oldnmemb
128is ignored and the call is equivalent to
129.Fn calloc .
130If
131.Fa ptr
132is not a
133.Dv NULL
134pointer,
135.Fa oldnmemb
136must be a value such that
137.Fa oldnmemb
138*
139.Fa size
140is the size of an earlier allocation that returned
141.Fa ptr ,
142otherwise the behaviour is undefined.
143.Pp
144The
116.Fn free 145.Fn free
117function causes the space pointed to by 146function causes the space pointed to by
118.Fa ptr 147.Fa ptr
@@ -129,16 +158,18 @@ If
129was previously freed by 158was previously freed by
130.Fn free , 159.Fn free ,
131.Fn realloc , 160.Fn realloc ,
161.Fn reallocarray
132or 162or
133.Fn reallocarray , 163.Fn recallocarray ,
134the behavior is undefined and the double free is a security concern. 164the behavior is undefined and the double free is a security concern.
135.Sh RETURN VALUES 165.Sh RETURN VALUES
136Upon successful completion, the functions 166Upon successful completion, the functions
137.Fn malloc , 167.Fn malloc ,
138.Fn calloc , 168.Fn calloc ,
139.Fn realloc , 169.Fn realloc ,
140and
141.Fn reallocarray 170.Fn reallocarray
171and
172.Fn recallocarray
142return a pointer to the allocated space; otherwise, a 173return a pointer to the allocated space; otherwise, a
143.Dv NULL 174.Dv NULL
144pointer is returned and 175pointer is returned and
@@ -161,15 +192,31 @@ If multiplying
161and 192and
162.Fa size 193.Fa size
163results in integer overflow, 194results in integer overflow,
164.Fn calloc 195.Fn calloc ,
165and
166.Fn reallocarray 196.Fn reallocarray
197and
198.Fn recallocarray
167return 199return
168.Dv NULL 200.Dv NULL
169and set 201and set
170.Va errno 202.Va errno
171to 203to
172.Er ENOMEM . 204.Er ENOMEM .
205.Pp
206If
207.Fa ptr
208is not NULL and multiplying
209.Fa oldnmemb
210and
211.Fa size
212results in integer overflow
213.Fn recallocarray
214returns
215.Dv NULL
216and sets
217.Va errno
218to
219.Er EINVAL .
173.Sh IDIOMS 220.Sh IDIOMS
174Consider 221Consider
175.Fn calloc 222.Fn calloc
@@ -264,6 +311,17 @@ Use the following:
264.Bd -literal -offset indent 311.Bd -literal -offset indent
265newp = realloc(p, newsize); 312newp = realloc(p, newsize);
266.Ed 313.Ed
314.Pp
315The
316.Fn recallocarray
317function should be used for resizing objects containing sensitive data like
318keys.
319To avoid leaking information,
320it guarantees memory is cleared before placing it on the internal free list.
321A
322.Fn free
323call for such an object should still be preceded by a call to
324.Xr explicit_bzero 3 .
267.Sh ENVIRONMENT 325.Sh ENVIRONMENT
268.Bl -tag -width "/etc/malloc.conf" 326.Bl -tag -width "/etc/malloc.conf"
269.It Ev MALLOC_OPTIONS 327.It Ev MALLOC_OPTIONS
diff --git a/src/lib/libc/stdlib/recallocarray.c b/src/lib/libc/stdlib/recallocarray.c
new file mode 100644
index 0000000000..a2f37fe81a
--- /dev/null
+++ b/src/lib/libc/stdlib/recallocarray.c
@@ -0,0 +1,81 @@
1/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
2/*
3 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <errno.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <unistd.h>
23
24/*
25 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27 */
28#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30void *
31recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32{
33 size_t oldsize, newsize;
34 void *newptr;
35
36 if (ptr == NULL)
37 return calloc(newnmemb, size);
38
39 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41 errno = ENOMEM;
42 return NULL;
43 }
44 newsize = newnmemb * size;
45
46 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48 errno = EINVAL;
49 return NULL;
50 }
51 oldsize = oldnmemb * size;
52
53 /*
54 * Don't bother too much if we're shrinking just a bit,
55 * we do not shrink for series of small steps, oh well.
56 */
57 if (newsize <= oldsize) {
58 size_t d = oldsize - newsize;
59
60 if (d < oldsize / 2 && d < getpagesize()) {
61 memset((char *)ptr + newsize, 0, d);
62 return ptr;
63 }
64 }
65
66 newptr = malloc(newsize);
67 if (newptr == NULL)
68 return NULL;
69
70 if (newsize > oldsize) {
71 memcpy(newptr, ptr, oldsize);
72 memset((char *)newptr + oldsize, 0, newsize - oldsize);
73 } else
74 memcpy(newptr, ptr, newsize);
75
76 explicit_bzero(ptr, oldsize);
77 free(ptr);
78
79 return newptr;
80}
81DEF_WEAK(recallocarray);