Sun, 21 Jan 2018 10:13:21 +0100
adds integer overflow checks
src/Makefile.am | file | annotate | diff | comparison | revisions | |
src/buffer.c | file | annotate | diff | comparison | revisions | |
src/mempool.c | file | annotate | diff | comparison | revisions | |
src/string.c | file | annotate | diff | comparison | revisions | |
src/ucx.c | file | annotate | diff | comparison | revisions | |
src/ucx/ucx.h | file | annotate | diff | comparison | revisions | |
test/mpool_tests.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/Makefile.am Tue Jan 02 17:00:21 2018 +0100 1.2 +++ b/src/Makefile.am Sun Jan 21 10:13:21 2018 +0100 1.3 @@ -40,6 +40,7 @@ 1.4 libucx_la_SOURCES += logging.c 1.5 libucx_la_SOURCES += buffer.c 1.6 libucx_la_SOURCES += stack.c 1.7 +libucx_la_SOURCES += ucx.c 1.8 1.9 ucxdir = $(includedir)/ucx 1.10 ucx_HEADERS = ucx/allocator.h
2.1 --- a/src/buffer.c Tue Jan 02 17:00:21 2018 +0100 2.2 +++ b/src/buffer.c Sun Jan 21 10:13:21 2018 +0100 2.3 @@ -151,7 +151,10 @@ 2.4 2.5 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 2.6 UcxBuffer *buffer) { 2.7 - size_t len = size * nitems; 2.8 + size_t len; 2.9 + if(ucx_szmul(size, nitems, &len)) { 2.10 + return 0; 2.11 + } 2.12 size_t required = buffer->pos + len; 2.13 if (buffer->pos > required) { 2.14 return 0; 2.15 @@ -185,7 +188,10 @@ 2.16 2.17 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 2.18 UcxBuffer *buffer) { 2.19 - size_t len = size * nitems; 2.20 + size_t len; 2.21 + if(ucx_szmul(size, nitems, &len)) { 2.22 + return 0; 2.23 + } 2.24 if (buffer->pos + len > buffer->size) { 2.25 len = buffer->size - buffer->pos; 2.26 if (size > 1) len -= len%size;
3.1 --- a/src/mempool.c Tue Jan 02 17:00:21 2018 +0100 3.2 +++ b/src/mempool.c Sun Jan 21 10:13:21 2018 +0100 3.3 @@ -65,12 +65,17 @@ 3.4 } 3.5 3.6 UcxMempool *ucx_mempool_new(size_t n) { 3.7 + size_t poolsz; 3.8 + if(ucx_szmul(n, sizeof(void*), &poolsz)) { 3.9 + return NULL; 3.10 + } 3.11 + 3.12 UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); 3.13 if (!pool) { 3.14 return NULL; 3.15 } 3.16 3.17 - pool->data = (void**) malloc(n * sizeof(void*)); 3.18 + pool->data = (void**) malloc(poolsz); 3.19 if (pool->data == NULL) { 3.20 free(pool); 3.21 return NULL; 3.22 @@ -100,7 +105,12 @@ 3.23 return 1; 3.24 } 3.25 3.26 - void **data = (void**) realloc(pool->data, newcap*sizeof(void*)); 3.27 + size_t newcapsz; 3.28 + if(ucx_szmul(newcap, sizeof(void*), &newcapsz)) { 3.29 + return 1; 3.30 + } 3.31 + 3.32 + void **data = (void**) realloc(pool->data, newcapsz); 3.33 if (data) { 3.34 pool->data = data; 3.35 pool->size = newcap; 3.36 @@ -111,6 +121,10 @@ 3.37 } 3.38 3.39 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { 3.40 + if(((size_t)-1) - sizeof(ucx_destructor) < n) { 3.41 + return NULL; 3.42 + } 3.43 + 3.44 if (pool->ndata >= pool->size) { 3.45 size_t newcap = pool->size*2; 3.46 if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) { 3.47 @@ -132,7 +146,12 @@ 3.48 } 3.49 3.50 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { 3.51 - void *ptr = ucx_mempool_malloc(pool, nelem*elsize); 3.52 + size_t msz; 3.53 + if(ucx_szmul(nelem, elsize, &msz)) { 3.54 + return NULL; 3.55 + } 3.56 + 3.57 + void *ptr = ucx_mempool_malloc(pool, msz); 3.58 if (!ptr) { 3.59 return NULL; 3.60 } 3.61 @@ -141,6 +160,10 @@ 3.62 } 3.63 3.64 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { 3.65 + if(((size_t)-1) - sizeof(ucx_destructor) < n) { 3.66 + return NULL; 3.67 + } 3.68 + 3.69 char *mem = ((char*)ptr) - sizeof(ucx_destructor); 3.70 char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); 3.71 if (!newm) {
4.1 --- a/src/string.c Tue Jan 02 17:00:21 2018 +0100 4.2 +++ b/src/string.c Sun Jan 21 10:13:21 2018 +0100 4.3 @@ -269,14 +269,18 @@ 4.4 } else /* no match possible */ { 4.5 *n = 1; 4.6 sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)); 4.7 - *result = sstrdup_a(allocator, s); 4.8 + if(result) { 4.9 + *result = sstrdup_a(allocator, s); 4.10 + } else { 4.11 + *n = -2; 4.12 + } 4.13 return result; 4.14 } 4.15 } 4.16 4.17 ssize_t nmax = *n; 4.18 size_t arrlen = 16; 4.19 - sstr_t* result = (sstr_t*) almalloc(allocator, arrlen*sizeof(sstr_t)); 4.20 + sstr_t* result = (sstr_t*) alcalloc(allocator, arrlen, sizeof(sstr_t)); 4.21 4.22 if (result) { 4.23 sstr_t curpos = s; 4.24 @@ -310,8 +314,12 @@ 4.25 j++; 4.26 if (j > arrlen) { 4.27 arrlen *= 2; 4.28 - sstr_t* reallocated = (sstr_t*) alrealloc( 4.29 - allocator, result, arrlen*sizeof(sstr_t)); 4.30 + size_t reallocsz; 4.31 + sstr_t* reallocated = NULL; 4.32 + if(!ucx_szmul(arrlen, sizeof(sstr_t), &reallocsz)) { 4.33 + reallocated = (sstr_t*) alrealloc( 4.34 + allocator, result, reallocsz); 4.35 + } 4.36 if (reallocated) { 4.37 result = reallocated; 4.38 } else {
5.1 --- a/src/ucx.c Tue Jan 02 17:00:21 2018 +0100 5.2 +++ b/src/ucx.c Sun Jan 21 10:13:21 2018 +0100 5.3 @@ -44,3 +44,20 @@ 5.4 */ 5.5 5.6 #include "ucx/ucx.h" 5.7 + 5.8 +#ifndef UCX_MUL_BUILTIN 5.9 +int ucx_szmul(size_t a, size_t b, size_t *result) { 5.10 + if(a == 0 || b == 0) { 5.11 + *result = 0; 5.12 + return 1; 5.13 + } 5.14 + size_t r = a * b; 5.15 + if(r / b == a) { 5.16 + *result = r; 5.17 + return 0; 5.18 + } else { 5.19 + *result = 0; 5.20 + return 1; 5.21 + } 5.22 +} 5.23 +#endif
6.1 --- a/src/ucx/ucx.h Tue Jan 02 17:00:21 2018 +0100 6.2 +++ b/src/ucx/ucx.h Sun Jan 21 10:13:21 2018 +0100 6.3 @@ -131,6 +131,15 @@ 6.4 */ 6.5 typedef size_t(*read_func)(void*, size_t, size_t, void*); 6.6 6.7 + 6.8 + 6.9 +#if defined(__GNUC__) || defined(__clang__) 6.10 +#define UCX_MUL_BUILTIN 6.11 +#define ucx_szmul(a, b, result) __builtin_umull_overflow(a, b, result) 6.12 +#else 6.13 +int ucx_szmul(size_t a, size_t b, size_t *result); 6.14 +#endif 6.15 + 6.16 #ifdef __cplusplus 6.17 } 6.18 #endif
7.1 --- a/test/mpool_tests.c Tue Jan 02 17:00:21 2018 +0100 7.2 +++ b/test/mpool_tests.c Sun Jan 21 10:13:21 2018 +0100 7.3 @@ -75,6 +75,13 @@ 7.4 7.5 UCX_TEST_ASSERT(*test == 5, "wrong pointer"); 7.6 7.7 + // overflow test 7.8 + void *n0 = ucx_mempool_malloc(pool, (size_t)-1); 7.9 + void *n1 = ucx_mempool_malloc(pool, ((size_t)-1) - sizeof(void*)/2); 7.10 + 7.11 + UCX_TEST_ASSERT(n0 == NULL, "should not allocate SIZE_MAX bytes"); 7.12 + UCX_TEST_ASSERT(n1 == NULL, "should detect integer overflow"); 7.13 + 7.14 UCX_TEST_END 7.15 ucx_mempool_destroy(pool); 7.16 } 7.17 @@ -89,6 +96,13 @@ 7.18 UCX_TEST_ASSERT(test != NULL, "no memory for test data"); 7.19 UCX_TEST_ASSERT(test[0] == 0 && test[1] == 0, "failed"); 7.20 7.21 + // overflow test 7.22 + void *n0 = ucx_mempool_calloc(pool, (size_t)-1, 1); 7.23 + void *n1 = ucx_mempool_calloc(pool, ((size_t)-1)/2, 3); 7.24 + 7.25 + UCX_TEST_ASSERT(n0 == NULL, "should not allocate SIZE_MAX bytes"); 7.26 + UCX_TEST_ASSERT(n1 == NULL, "should detect integer overflow"); 7.27 + 7.28 UCX_TEST_END 7.29 ucx_mempool_destroy(pool); 7.30 }