# HG changeset patch # User Olaf Wintermann # Date 1516526001 -3600 # Node ID 3d80d425543bb276b0e254ac89d69ca7b77036e6 # Parent 591473851c958e4a437a9f829ff5f565e3449567 adds integer overflow checks diff -r 591473851c95 -r 3d80d425543b src/Makefile.am --- a/src/Makefile.am Tue Jan 02 17:00:21 2018 +0100 +++ b/src/Makefile.am Sun Jan 21 10:13:21 2018 +0100 @@ -40,6 +40,7 @@ libucx_la_SOURCES += logging.c libucx_la_SOURCES += buffer.c libucx_la_SOURCES += stack.c +libucx_la_SOURCES += ucx.c ucxdir = $(includedir)/ucx ucx_HEADERS = ucx/allocator.h diff -r 591473851c95 -r 3d80d425543b src/buffer.c --- a/src/buffer.c Tue Jan 02 17:00:21 2018 +0100 +++ b/src/buffer.c Sun Jan 21 10:13:21 2018 +0100 @@ -151,7 +151,10 @@ size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, UcxBuffer *buffer) { - size_t len = size * nitems; + size_t len; + if(ucx_szmul(size, nitems, &len)) { + return 0; + } size_t required = buffer->pos + len; if (buffer->pos > required) { return 0; @@ -185,7 +188,10 @@ size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, UcxBuffer *buffer) { - size_t len = size * nitems; + size_t len; + if(ucx_szmul(size, nitems, &len)) { + return 0; + } if (buffer->pos + len > buffer->size) { len = buffer->size - buffer->pos; if (size > 1) len -= len%size; diff -r 591473851c95 -r 3d80d425543b src/mempool.c --- a/src/mempool.c Tue Jan 02 17:00:21 2018 +0100 +++ b/src/mempool.c Sun Jan 21 10:13:21 2018 +0100 @@ -65,12 +65,17 @@ } UcxMempool *ucx_mempool_new(size_t n) { + size_t poolsz; + if(ucx_szmul(n, sizeof(void*), &poolsz)) { + return NULL; + } + UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); if (!pool) { return NULL; } - pool->data = (void**) malloc(n * sizeof(void*)); + pool->data = (void**) malloc(poolsz); if (pool->data == NULL) { free(pool); return NULL; @@ -100,7 +105,12 @@ return 1; } - void **data = (void**) realloc(pool->data, newcap*sizeof(void*)); + size_t newcapsz; + if(ucx_szmul(newcap, sizeof(void*), &newcapsz)) { + return 1; + } + + void **data = (void**) realloc(pool->data, newcapsz); if (data) { pool->data = data; pool->size = newcap; @@ -111,6 +121,10 @@ } void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { + if(((size_t)-1) - sizeof(ucx_destructor) < n) { + return NULL; + } + if (pool->ndata >= pool->size) { size_t newcap = pool->size*2; if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) { @@ -132,7 +146,12 @@ } void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { - void *ptr = ucx_mempool_malloc(pool, nelem*elsize); + size_t msz; + if(ucx_szmul(nelem, elsize, &msz)) { + return NULL; + } + + void *ptr = ucx_mempool_malloc(pool, msz); if (!ptr) { return NULL; } @@ -141,6 +160,10 @@ } void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { + if(((size_t)-1) - sizeof(ucx_destructor) < n) { + return NULL; + } + char *mem = ((char*)ptr) - sizeof(ucx_destructor); char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); if (!newm) { diff -r 591473851c95 -r 3d80d425543b src/string.c --- a/src/string.c Tue Jan 02 17:00:21 2018 +0100 +++ b/src/string.c Sun Jan 21 10:13:21 2018 +0100 @@ -269,14 +269,18 @@ } else /* no match possible */ { *n = 1; sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)); - *result = sstrdup_a(allocator, s); + if(result) { + *result = sstrdup_a(allocator, s); + } else { + *n = -2; + } return result; } } ssize_t nmax = *n; size_t arrlen = 16; - sstr_t* result = (sstr_t*) almalloc(allocator, arrlen*sizeof(sstr_t)); + sstr_t* result = (sstr_t*) alcalloc(allocator, arrlen, sizeof(sstr_t)); if (result) { sstr_t curpos = s; @@ -310,8 +314,12 @@ j++; if (j > arrlen) { arrlen *= 2; - sstr_t* reallocated = (sstr_t*) alrealloc( - allocator, result, arrlen*sizeof(sstr_t)); + size_t reallocsz; + sstr_t* reallocated = NULL; + if(!ucx_szmul(arrlen, sizeof(sstr_t), &reallocsz)) { + reallocated = (sstr_t*) alrealloc( + allocator, result, reallocsz); + } if (reallocated) { result = reallocated; } else { diff -r 591473851c95 -r 3d80d425543b src/ucx.c --- a/src/ucx.c Tue Jan 02 17:00:21 2018 +0100 +++ b/src/ucx.c Sun Jan 21 10:13:21 2018 +0100 @@ -44,3 +44,20 @@ */ #include "ucx/ucx.h" + +#ifndef UCX_MUL_BUILTIN +int ucx_szmul(size_t a, size_t b, size_t *result) { + if(a == 0 || b == 0) { + *result = 0; + return 1; + } + size_t r = a * b; + if(r / b == a) { + *result = r; + return 0; + } else { + *result = 0; + return 1; + } +} +#endif diff -r 591473851c95 -r 3d80d425543b src/ucx/ucx.h --- a/src/ucx/ucx.h Tue Jan 02 17:00:21 2018 +0100 +++ b/src/ucx/ucx.h Sun Jan 21 10:13:21 2018 +0100 @@ -131,6 +131,15 @@ */ typedef size_t(*read_func)(void*, size_t, size_t, void*); + + +#if defined(__GNUC__) || defined(__clang__) +#define UCX_MUL_BUILTIN +#define ucx_szmul(a, b, result) __builtin_umull_overflow(a, b, result) +#else +int ucx_szmul(size_t a, size_t b, size_t *result); +#endif + #ifdef __cplusplus } #endif diff -r 591473851c95 -r 3d80d425543b test/mpool_tests.c --- a/test/mpool_tests.c Tue Jan 02 17:00:21 2018 +0100 +++ b/test/mpool_tests.c Sun Jan 21 10:13:21 2018 +0100 @@ -75,6 +75,13 @@ UCX_TEST_ASSERT(*test == 5, "wrong pointer"); + // overflow test + void *n0 = ucx_mempool_malloc(pool, (size_t)-1); + void *n1 = ucx_mempool_malloc(pool, ((size_t)-1) - sizeof(void*)/2); + + UCX_TEST_ASSERT(n0 == NULL, "should not allocate SIZE_MAX bytes"); + UCX_TEST_ASSERT(n1 == NULL, "should detect integer overflow"); + UCX_TEST_END ucx_mempool_destroy(pool); } @@ -89,6 +96,13 @@ UCX_TEST_ASSERT(test != NULL, "no memory for test data"); UCX_TEST_ASSERT(test[0] == 0 && test[1] == 0, "failed"); + // overflow test + void *n0 = ucx_mempool_calloc(pool, (size_t)-1, 1); + void *n1 = ucx_mempool_calloc(pool, ((size_t)-1)/2, 3); + + UCX_TEST_ASSERT(n0 == NULL, "should not allocate SIZE_MAX bytes"); + UCX_TEST_ASSERT(n1 == NULL, "should detect integer overflow"); + UCX_TEST_END ucx_mempool_destroy(pool); }