From 322c3a8a8a986a041e28a9a9839bb4f0d808a3d0 Mon Sep 17 00:00:00 2001 From: mmcc Date: Fri, 16 Oct 2015 03:17:56 +0000 Subject: [PATCH] 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@. --- bin/ksh/alloc.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) 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 #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) { -- 2.20.1