Import reallocarray(3) from OpenBSD
Add a manpage for it, assign the copyright to the OpenBSD project on it since it is mostly copy/paste from OpenBSD manpage. style(9) fixes Differential Revision: https://reviews.freebsd.org/D2420 Reviewed by: kib
This commit is contained in:
parent
24f93ee714
commit
450dfafb15
@ -111,6 +111,9 @@ long double
|
||||
strtold(const char * __restrict, char ** __restrict);
|
||||
unsigned long
|
||||
strtoul(const char * __restrict, char ** __restrict, int);
|
||||
#ifdef __BSD_VISIBLE
|
||||
void *reallocarray(void *, size_t, size_t);
|
||||
#endif
|
||||
int system(const char *);
|
||||
int wctomb(char *, wchar_t);
|
||||
size_t wcstombs(char * __restrict, const wchar_t * __restrict, size_t);
|
||||
|
@ -10,7 +10,8 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \
|
||||
merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c quick_exit.c \
|
||||
radixsort.c rand.c \
|
||||
random.c reallocf.c realpath.c remque.c strfmon.c strtoimax.c \
|
||||
random.c reallocarray.c reallocf.c realpath.c remque.c strfmon.c \
|
||||
strtoimax.c \
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
|
||||
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
|
||||
@ -25,7 +26,7 @@ MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 \
|
||||
hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
|
||||
lsearch.3 memory.3 ptsname.3 qsort.3 \
|
||||
quick_exit.3 \
|
||||
radixsort.3 rand.3 random.3 reallocf.3 \
|
||||
radixsort.3 rand.3 random.3 reallocarray.3 reallocf.3 \
|
||||
realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \
|
||||
tsearch.3
|
||||
|
||||
|
@ -113,6 +113,7 @@ FBSD_1.4 {
|
||||
hcreate_r;
|
||||
hdestroy_r;
|
||||
hsearch_r;
|
||||
reallocarray;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
|
136
lib/libc/stdlib/reallocarray.3
Normal file
136
lib/libc/stdlib/reallocarray.3
Normal file
@ -0,0 +1,136 @@
|
||||
.\" Copyright (c) 2015 OpenBSD
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the American National Standards Committee X3, on Information
|
||||
.\" Processing Systems.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 1, 2015
|
||||
.Dt REALLOCARRAY 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm reallocarray
|
||||
.Nd memory reallocation function
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In stdlib.h
|
||||
.Ft void *
|
||||
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn reallocarray
|
||||
except it operates on
|
||||
.Fa nmemb
|
||||
members of size
|
||||
.Fa size
|
||||
and checks for integer overflow in the calculation
|
||||
.Fa nmemb
|
||||
*
|
||||
.Fa size .
|
||||
.Sh RETURN VALUES
|
||||
.Fn reallocarray
|
||||
return a pointer to the allocated space; otherwise, a
|
||||
.Dv NULL
|
||||
pointer is returned and
|
||||
.Va errno
|
||||
is set to
|
||||
.Er ENOMEM .
|
||||
.Sh EXAMPLES
|
||||
Consider
|
||||
.Fn reallocarray
|
||||
when there is multiplication in the
|
||||
.Fa size
|
||||
argument of
|
||||
.Fn malloc
|
||||
or
|
||||
.Fn realloc .
|
||||
For example, avoid this common idiom as it may lead to integer overflow:
|
||||
.Bd -literal -offset indent
|
||||
if ((p = malloc(num * size)) == NULL)
|
||||
err(1, "malloc");
|
||||
.Ed
|
||||
.Pp
|
||||
A drop-in replacement is the
|
||||
.Ox
|
||||
extension
|
||||
.Fn reallocarray :
|
||||
.Bd -literal -offset indent
|
||||
if ((p = reallocarray(NULL, num, size)) == NULL)
|
||||
err(1, "reallocarray");
|
||||
.Ed
|
||||
.Pp
|
||||
When using
|
||||
.Fn realloc ,
|
||||
be careful to avoid the following idiom:
|
||||
.Bd -literal -offset indent
|
||||
size += 50;
|
||||
if ((p = realloc(p, size)) == NULL)
|
||||
return (NULL);
|
||||
.Ed
|
||||
.Pp
|
||||
Do not adjust the variable describing how much memory has been allocated
|
||||
until the allocation has been successful.
|
||||
This can cause aberrant program behavior if the incorrect size value is used.
|
||||
In most cases, the above sample will also result in a leak of memory.
|
||||
As stated earlier, a return value of
|
||||
.Dv NULL
|
||||
indicates that the old object still remains allocated.
|
||||
Better code looks like this:
|
||||
.Bd -literal -offset indent
|
||||
newsize = size + 50;
|
||||
if ((newp = realloc(p, newsize)) == NULL) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
size = 0;
|
||||
return (NULL);
|
||||
}
|
||||
p = newp;
|
||||
size = newsize;
|
||||
.Ed
|
||||
.Pp
|
||||
As with
|
||||
.Fn malloc ,
|
||||
it is important to ensure the new size value will not overflow;
|
||||
i.e. avoid allocations like the following:
|
||||
.Bd -literal -offset indent
|
||||
if ((newp = realloc(p, num * size)) == NULL) {
|
||||
...
|
||||
.Ed
|
||||
.Pp
|
||||
Instead, use
|
||||
.Fn reallocarray :
|
||||
.Bd -literal -offset indent
|
||||
if ((newp = reallocarray(p, num, size)) == NULL) {
|
||||
...
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr realloc 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn reallocf
|
||||
function first appeared in
|
||||
.Ox 5.6 .
|
42
lib/libc/stdlib/reallocarray.c
Normal file
42
lib/libc/stdlib/reallocarray.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
|
||||
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
|
||||
*/
|
||||
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
|
||||
|
||||
void *
|
||||
reallocarray(void *optr, size_t nmemb, size_t size)
|
||||
{
|
||||
|
||||
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
|
||||
nmemb > 0 && SIZE_MAX / nmemb < size) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
return (realloc(optr, size * nmemb));
|
||||
}
|
Loading…
Reference in New Issue
Block a user