diff options
author | mmcc <mmcc@cvs.openbsd.org> | 2015-10-16 03:17:57 +0000 |
---|---|---|
committer | mmcc <mmcc@cvs.openbsd.org> | 2015-10-16 03:17:57 +0000 |
commit | e9e5c6509fa930fba0af08f22ca973e35dd16cee (patch) | |
tree | dc08dad050a2580c1305a767729bc11b8f7d279a /bin | |
parent | 8e1a3ce9e660f70b76fa83fee6207d4f9790b2e2 (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.c | 27 |
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) { |