From a0aa1219889791496c9c9890059d9bb0c25e85b4 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 12 Jan 2019 14:01:40 +0100
Subject: [PATCH] reallocarray

---
 include/stdlib.h               |   1 +
 lib/libc/Versions.def          |   4 +
 lib/libc/stdlib/Makefile.inc   |   5 +-
 lib/libc/stdlib/Symbol.map     |   4 +
 lib/libc/stdlib/reallocarray.3 | 142 +++++++++++++++++++++++++++++++++
 lib/libc/stdlib/reallocarray.c |  38 +++++++++
 sbin/dhcpcd/Makefile           |   2 +-
 sbin/dhcpcd/config.h           |   1 -
 sys/sys/param.h                |   3 +-
 9 files changed, 195 insertions(+), 5 deletions(-)
 create mode 100644 lib/libc/stdlib/reallocarray.3
 create mode 100644 lib/libc/stdlib/reallocarray.c

diff --git a/include/stdlib.h b/include/stdlib.h
index e0daa6ca56..16637d1883 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -299,6 +299,7 @@ void	 qsort_r(void *, size_t, size_t, void *,
 		 int (*)(void *, const void *, const void *));
 int	 radixsort(const unsigned char **, int, const unsigned char *,
 		   unsigned int);
+void	*reallocarray(void *, size_t, size_t) __heedresult __alloc_size2(2, 3);
 void	*reallocf(void *, size_t) __heedresult __alloc_size(2);
 int	 rpmatch(const char *);
 void	 setprogname(const char *);
diff --git a/lib/libc/Versions.def b/lib/libc/Versions.def
index 3bad35a966..232608b5da 100644
--- a/lib/libc/Versions.def
+++ b/lib/libc/Versions.def
@@ -41,6 +41,10 @@ DF502.0 {
 DF504.0 {
 } DF502.0;
 
+# version for DragonFly 5.5
+DF506.0 {
+} DF504.0;
+
 # This is our private namespace.  Any global interfaces that are
 # strictly for use only by other DragonFly applications and libraries
 # are listed here.  We use a separate namespace so we can write
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index 7e6049b1a9..a80357a2e4 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -12,7 +12,8 @@ MISRCS+=a64l.c abort.c abs.c atexit.c aligned_alloc.c \
 	getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \
 	insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \
 	merge.c ptsname.c qsort.c qsort_r.c quick_exit.c \
-	radixsort.c rand.c random.c reallocf.c realpath.c remque.c \
+	radixsort.c rand.c random.c \
+	reallocarray.c reallocf.c realpath.c remque.c \
 	strfmon.c strsuftoll.c strtoimax.c \
 	strtol.c strtoll.c strtonum.c strtoq.c strtoul.c strtoull.c \
 	strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
@@ -40,7 +41,7 @@ MAN+=	a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 \
 	hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
 	lsearch.3 malloc.3 memory.3 posix_memalign.3 posix_openpt.3 \
 	ptsname.3 qsort.3 quick_exit.3 \
-	radixsort.3 rand.3 random.3 realpath.3 \
+	radixsort.3 rand.3 random.3 realpath.3 reallocarray.3 \
 	strfmon.3 strsuftoll.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \
 	tsearch.3
 
diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map
index f270ddf306..efb0c2e40b 100644
--- a/lib/libc/stdlib/Symbol.map
+++ b/lib/libc/stdlib/Symbol.map
@@ -116,6 +116,10 @@ DF504.0 {
     strsuftollx;
 };
 
+DF506.0 {
+    reallocarray;
+};
+
 /*
  * ignore WEAK:  __pthread_cxa_finalize;
  */
diff --git a/lib/libc/stdlib/reallocarray.3 b/lib/libc/stdlib/reallocarray.3
new file mode 100644
index 0000000000..8c17edecda
--- /dev/null
+++ b/lib/libc/stdlib/reallocarray.3
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\"	The Regents of the University of California.  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: head/lib/libc/stdlib/reallocarray.3 282472 2015-05-05 10:44:17Z pluknet $
+.\"
+.Dd January 11, 2019
+.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 number" "size_t size"
+.Sh DESCRIPTION
+The
+.Fn reallocarray
+function is similar to the
+.Fn realloc
+function
+except it operates on
+.Fa number
+members of size
+.Fa size
+and checks for integer overflow in the calculation
+.Fa number
+*
+.Fa size .
+.Sh RETURN VALUES
+The
+.Fn reallocarray
+function returns 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 reallocarray
+function first appeared in
+.Ox 5.6
+and
+.Fx 11.0 .
diff --git a/lib/libc/stdlib/reallocarray.c b/lib/libc/stdlib/reallocarray.c
new file mode 100644
index 0000000000..f0521cabdf
--- /dev/null
+++ b/lib/libc/stdlib/reallocarray.c
@@ -0,0 +1,38 @@
+/*	$OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther 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/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 *ptr, size_t number, size_t size)
+{
+	if ((number >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    number > 0 && SIZE_MAX / number < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	return realloc(ptr, size * number);
+}
diff --git a/sbin/dhcpcd/Makefile b/sbin/dhcpcd/Makefile
index 601c5777fb..5ab6c2036a 100644
--- a/sbin/dhcpcd/Makefile
+++ b/sbin/dhcpcd/Makefile
@@ -26,7 +26,7 @@ CFLAGS+=	-DDHCP6
 SRCS+=		dhcp6.c
 
 .PATH:		${DISTDIR}/compat
-SRCS+=		pidfile.c reallocarray.c strtoi.c strtou.c
+SRCS+=		pidfile.c strtoi.c strtou.c
 .PATH:		${DISTDIR}/compat/crypt
 SRCS+=		hmac.c
 
diff --git a/sbin/dhcpcd/config.h b/sbin/dhcpcd/config.h
index 27a5f71a78..095d3e3fff 100644
--- a/sbin/dhcpcd/config.h
+++ b/sbin/dhcpcd/config.h
@@ -8,7 +8,6 @@
 #define	TAILQ_FOREACH_SAFE	TAILQ_FOREACH_MUTABLE
 #define	HAVE_KQUEUE
 #define	HAVE_REALLOCARRAY
-#include			"compat/reallocarray.h"
 #include			"compat/pidfile.h"
 #include			"compat/strtoi.h"
 #define	HAVE_MD5_H
diff --git a/sys/sys/param.h b/sys/sys/param.h
index b541a78dd5..2beff21a91 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -190,9 +190,10 @@
  * 500317 - add wait6() and waitid() syscalls
  * 500400 - 5.4 release
  * 500500 - 5.5 development
+ * 500501 - reallocarray() added to libc
  */
 #undef __DragonFly_version
-#define __DragonFly_version 500500	/* propagated to newvers */
+#define __DragonFly_version 500501	/* propagated to newvers */
 
 #include <sys/_null.h>
 
-- 
2.19.2

