adds integer overflow checks

Sun, 21 Jan 2018 10:13:21 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 21 Jan 2018 10:13:21 +0100
changeset 270
3d80d425543b
parent 269
591473851c95
child 271
47b8ea435902

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  }

mercurial