summaryrefslogtreecommitdiff
path: root/portable/reallocarray.c
diff options
context:
space:
mode:
authorRuss Allbery <eagle@eyrie.org>2014-07-16 13:46:50 -0700
committerRuss Allbery <eagle@eyrie.org>2014-07-16 13:46:50 -0700
commit1796d631f0846ec98cd286bc4284898a7300ee78 (patch)
tree6fd42de6dc858ef06c6d270410c32ec61f39e593 /portable/reallocarray.c
parentf5194217566a6f4cdeffbae551153feb1412210d (diff)
parent6409733ee3b7b1910dc1c166a392cc628834146c (diff)
Merge tag 'upstream/1.1' into debian
Upstream version 1.1 Conflicts: NEWS README client/keytab.c perl/lib/Wallet/ACL.pm perl/sql/Wallet-Schema-0.08-PostgreSQL.sql perl/t/general/admin.t perl/t/verifier/ldap-attr.t Change-Id: I1a1dc09b97c9258e61f1c8877d0837193c8ae2c6
Diffstat (limited to 'portable/reallocarray.c')
-rw-r--r--portable/reallocarray.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/portable/reallocarray.c b/portable/reallocarray.c
new file mode 100644
index 0000000..7d40a7a
--- /dev/null
+++ b/portable/reallocarray.c
@@ -0,0 +1,56 @@
+/*
+ * Replacement for a missing reallocarray.
+ *
+ * Provides the same functionality as the OpenBSD library function reallocrray
+ * for those systems that don't have it. This function is the same as
+ * realloc, but takes the size arguments in the same form as calloc and checks
+ * for overflow so that the caller doesn't need to.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <errno.h>
+
+/*
+ * If we're running the test suite, rename reallocarray to avoid conflicts
+ * with the system version. #undef it first because some systems may define
+ * it to another name.
+ */
+#if TESTING
+# undef reallocarray
+# define reallocarray test_reallocarray
+void *test_reallocarray(void *, size_t, size_t);
+#endif
+
+/*
+ * nmemb * size cannot overflow if both are smaller than sqrt(SIZE_MAX). We
+ * can calculate that value statically by using 2^(sizeof(size_t) * 8) as the
+ * value of SIZE_MAX and then taking the square root, which gives
+ * 2^(sizeof(size_t) * 4). Compute the exponentiation with shift.
+ */
+#define CHECK_THRESHOLD (1UL << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *ptr, size_t nmemb, size_t size)
+{
+ if (nmemb >= CHECK_THRESHOLD || size >= CHECK_THRESHOLD)
+ if (nmemb > 0 && SIZE_MAX / nmemb <= size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(ptr, nmemb * size);
+}