diff --git a/elkscmd/test/libc/malloc.c b/elkscmd/test/libc/malloc.c index 180084cc3..5375da4cf 100644 --- a/elkscmd/test/libc/malloc.c +++ b/elkscmd/test/libc/malloc.c @@ -53,7 +53,9 @@ TEST_CASE(malloc_calloc) { free(p); } - /* TODO check for mult overflow */ + p = calloc(((unsigned)-1)>>2, 5); + EXPECT_EQ(errno, ENOMEM); + EXPECT_EQ_P(p, NULL); } TEST_CASE(malloc_realloc) { diff --git a/libc/malloc/calloc.c b/libc/malloc/calloc.c index e4b612017..539c9ec7d 100644 --- a/libc/malloc/calloc.c +++ b/libc/malloc/calloc.c @@ -1,13 +1,27 @@ +#include #include #include void * calloc(unsigned int elm, unsigned int sz) { - register unsigned int v; - register void *ptr; + unsigned int v; + void *ptr; - ptr = malloc(v = elm * sz); +#ifdef __GNUC__ + if (__builtin_umul_overflow(elm, sz, &v)) { + errno = ENOMEM; + return 0; + } +#else + v = elm * sz; + if (sz != 0 && v / sz != elm) { + errno = ENOMEM; + return 0; + } +#endif + + ptr = malloc(v); if (ptr) memset(ptr, 0, v);