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
--- 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
--- 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;
--- 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) {
--- 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 {
--- 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
--- 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
--- 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);
 }

mercurial