summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authormmcc <mmcc@cvs.openbsd.org>2015-10-16 03:17:57 +0000
committermmcc <mmcc@cvs.openbsd.org>2015-10-16 03:17:57 +0000
commite9e5c6509fa930fba0af08f22ca973e35dd16cee (patch)
treedc08dad050a2580c1305a767729bc11b8f7d279a /bin
parent8e1a3ce9e660f70b76fa83fee6207d4f9790b2e2 (diff)
Add allocarray(), an overflow-safe allocation function.
We avoided reallocation support because it demands more fancy footwork to deal with the prepended link struct. This has been on my mind for a while, and a 2010 security review of mksh by the Android security team's Chris Palmer suggested it. ok nicm@. Also discussed with millert@ and tedu@.
Diffstat (limited to 'bin')
-rw-r--r--bin/ksh/alloc.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/bin/ksh/alloc.c b/bin/ksh/alloc.c
index 7e41c2cd5be..3a6b35a79a4 100644
--- a/bin/ksh/alloc.c
+++ b/bin/ksh/alloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: alloc.c,v 1.8 2008/07/21 17:30:08 millert Exp $ */
+/* $OpenBSD: alloc.c,v 1.9 2015/10/16 03:17:56 mmcc Exp $ */
/*
* Copyright (c) 2002 Marc Espie.
*
@@ -28,6 +28,7 @@
* area-based allocation built on malloc/free
*/
+#include <stdint.h>
#include "sh.h"
struct link {
@@ -74,6 +75,30 @@ alloc(size_t size, Area *ap)
return L2P(l);
}
+/*
+ * Copied from calloc().
+ *
+ * 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 (1UL << (sizeof(size_t) * 4))
+
+void *
+allocarray(size_t nmemb, size_t size, Area *ap)
+{
+ /* condition logic cloned from calloc() */
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ internal_errorf(1, "unable to allocate memory");
+ }
+
+ /* additional check because alloc() allocates space for link */
+ if (nmemb * size > SIZE_MAX - sizeof(struct link))
+ internal_errorf(1, "unable to allocate memory");
+
+ return alloc(nmemb * size, ap);
+}
+
void *
aresize(void *ptr, size_t size, Area *ap)
{