summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@oracle.com>2019-08-03 16:13:21 -0700
committerAlan Coopersmith <alan.coopersmith@oracle.com>2019-08-03 19:31:14 -0700
commit27207d35d4b4bbd5d2b2c5f7e13a61ea43d04a4a (patch)
tree9cee5d22b4cc6b03924fbc5d225a1c020bc9401f
parent2178c7445a3464bd69637ad91a2dd0320a60e0df (diff)
Add reallocarray fallback if not provided by libc nor libbsd
Implementation copied from the Xserver Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
-rw-r--r--configure.ac2
-rw-r--r--src/util/reallocarray.c43
-rw-r--r--src/util/replace.h10
3 files changed, 54 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 970d9a3..8858b3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,7 +54,7 @@ AC_CHECK_HEADERS([endian.h poll.h sys/poll.h])
AC_CHECK_FUNCS([poll readlink])
AC_SEARCH_LIBS([strlcat], [bsd])
AC_CONFIG_LIBOBJ_DIR([src/util])
-AC_REPLACE_FUNCS([strlcat strlcpy])
+AC_REPLACE_FUNCS([reallocarray strlcat strlcpy])
# If the first PKG_CHECK_MODULES appears inside a conditional, pkg-config
# must first be located explicitly.
diff --git a/src/util/reallocarray.c b/src/util/reallocarray.c
new file mode 100644
index 0000000..025e24e
--- /dev/null
+++ b/src/util/reallocarray.c
@@ -0,0 +1,43 @@
+/* $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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "src/util/replace.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);
+}
diff --git a/src/util/replace.h b/src/util/replace.h
index 96ad001..16be544 100644
--- a/src/util/replace.h
+++ b/src/util/replace.h
@@ -31,6 +31,16 @@
#include <X11/Xfuncproto.h>
+#include <stdlib.h>
+#if defined(HAVE_LIBBSD) && defined(HAVE_REALLOCARRAY)
+#include <bsd/stdlib.h> /* for reallocarray */
+#endif
+
+#ifndef HAVE_REALLOCARRAY
+extern _X_HIDDEN void *
+reallocarray(void *optr, size_t nmemb, size_t size);
+#endif
+
#include <string.h>
#if defined(HAVE_LIBBSD) && defined(HAVE_STRLCPY)
#include <bsd/string.h> /* for strlcpy, strlcat */