You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2014/11/11 21:01:42 UTC

[5/5] lucy-clownfish git commit: Check for overflow of VArray size

Check for overflow of VArray size


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/79c0784a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/79c0784a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/79c0784a

Branch: refs/heads/master
Commit: 79c0784ab0b37d384b7d6830579f2f80f7c47a97
Parents: b3132fb
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue Nov 11 20:52:03 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Tue Nov 11 20:54:35 2014 +0100

----------------------------------------------------------------------
 runtime/core/Clownfish/Test/TestVArray.c | 61 ++++++++++++++++++++++++++-
 runtime/core/Clownfish/VArray.c          | 34 +++++++++++----
 2 files changed, 85 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/79c0784a/runtime/core/Clownfish/Test/TestVArray.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestVArray.c b/runtime/core/Clownfish/Test/TestVArray.c
index f817944..923d637 100644
--- a/runtime/core/Clownfish/Test/TestVArray.c
+++ b/runtime/core/Clownfish/Test/TestVArray.c
@@ -16,6 +16,7 @@
 
 #include <string.h>
 
+#define C_CFISH_VARRAY
 #define CFISH_USE_SHORT_NAMES
 #define TESTCFISH_USE_SHORT_NAMES
 
@@ -293,9 +294,66 @@ test_Clone_and_Shallow_Copy(TestBatchRunner *runner) {
     DECREF(twin);
 }
 
+static void
+S_overflow_Push(void *context) {
+    UNUSED_VAR(context);
+    VArray *array = VA_new(0);
+    array->cap  = UINT32_MAX;
+    array->size = array->cap;
+    VA_Push(array, (Obj*)CFISH_TRUE);
+}
+
+static void
+S_overflow_Unshift(void *context) {
+    UNUSED_VAR(context);
+    VArray *array = VA_new(0);
+    array->cap  = UINT32_MAX;
+    array->size = array->cap;
+    VA_Unshift(array, (Obj*)CFISH_TRUE);
+}
+
+static void
+S_overflow_Push_VArray(void *context) {
+    UNUSED_VAR(context);
+    VArray *array = VA_new(0);
+    array->cap  = 1000000000;
+    array->size = array->cap;
+    VArray *other = VA_new(0);
+    other->cap  = UINT32_MAX - array->cap + 1;
+    other->size = other->cap;
+    VA_Push_VArray(array, other);
+}
+
+static void
+S_overflow_Store(void *context) {
+    UNUSED_VAR(context);
+    VArray *array = VA_new(0);
+    VA_Store(array, UINT32_MAX, (Obj*)CFISH_TRUE);
+}
+
+static void
+S_test_exception(TestBatchRunner *runner, Err_Attempt_t func,
+                 const char *test_name) {
+    Err *error = Err_trap(func, NULL);
+    TEST_TRUE(runner, error != NULL, test_name);
+    DECREF(error);
+}
+
+static void
+test_exceptions(TestBatchRunner *runner) {
+    S_test_exception(runner, S_overflow_Push,
+                     "Push throws on overflow");
+    S_test_exception(runner, S_overflow_Unshift,
+                     "Unshift throws on overflow");
+    S_test_exception(runner, S_overflow_Push_VArray,
+                     "Push_VArray throws on overflow");
+    S_test_exception(runner, S_overflow_Store,
+                     "Store throws on overflow");
+}
+
 void
 TestVArray_Run_IMP(TestVArray *self, TestBatchRunner *runner) {
-    TestBatchRunner_Plan(runner, (TestBatch*)self, 43);
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 47);
     test_Equals(runner);
     test_Store_Fetch(runner);
     test_Push_Pop_Shift_Unshift(runner);
@@ -305,6 +363,7 @@ TestVArray_Run_IMP(TestVArray *self, TestBatchRunner *runner) {
     test_Push_VArray(runner);
     test_Slice(runner);
     test_Clone_and_Shallow_Copy(runner);
+    test_exceptions(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/79c0784a/runtime/core/Clownfish/VArray.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/VArray.c b/runtime/core/Clownfish/VArray.c
index 2472084..b6170d3 100644
--- a/runtime/core/Clownfish/VArray.c
+++ b/runtime/core/Clownfish/VArray.c
@@ -26,6 +26,9 @@
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Util/SortUtils.h"
 
+static CFISH_INLINE void
+SI_grow_by(VArray *self, uint32_t add_size);
+
 VArray*
 VA_new(uint32_t capacity) {
     VArray *self = (VArray*)Class_Make_Obj(VARRAY);
@@ -97,7 +100,7 @@ VA_Shallow_Copy_IMP(VArray *self) {
 void
 VA_Push_IMP(VArray *self, Obj *element) {
     if (self->size == self->cap) {
-        VA_Grow(self, Memory_oversize(self->size + 1, sizeof(Obj*)));
+        SI_grow_by(self, 1);
     }
     self->elems[self->size] = element;
     self->size++;
@@ -105,18 +108,16 @@ VA_Push_IMP(VArray *self, Obj *element) {
 
 void
 VA_Push_VArray_IMP(VArray *self, VArray *other) {
-    uint32_t tick = self->size;
-    uint32_t new_size = self->size + other->size;
-    if (new_size > self->cap) {
-        VA_Grow(self, Memory_oversize(new_size, sizeof(Obj*)));
+    if (other->size > self->cap - self->size) {
+        SI_grow_by(self, other->size);
     }
-    for (uint32_t i = 0; i < other->size; i++, tick++) {
+    for (uint32_t i = 0, tick = self->size; i < other->size; i++, tick++) {
         Obj *elem = VA_Fetch(other, i);
         if (elem != NULL) {
             self->elems[tick] = INCREF(elem);
         }
     }
-    self->size = new_size;
+    self->size += other->size;
 }
 
 Obj*
@@ -131,7 +132,7 @@ VA_Pop_IMP(VArray *self) {
 void
 VA_Unshift_IMP(VArray *self, Obj *elem) {
     if (self->size == self->cap) {
-        VA_Grow(self, Memory_oversize(self->size + 1, sizeof(Obj*)));
+        SI_grow_by(self, 1);
     }
     memmove(self->elems + 1, self->elems, self->size * sizeof(Obj*));
     self->elems[0] = elem;
@@ -166,7 +167,10 @@ VA_Fetch_IMP(VArray *self, uint32_t num) {
 void
 VA_Store_IMP(VArray *self, uint32_t tick, Obj *elem) {
     if (tick >= self->cap) {
-        VA_Grow(self, Memory_oversize(tick + 1, sizeof(Obj*)));
+        if (tick == UINT32_MAX) {
+            THROW(ERR, "Invalid tick");
+        }
+        SI_grow_by(self, tick + 1 - self->size);
     }
     if (tick < self->size) { DECREF(self->elems[tick]); }
     else                   { self->size = tick + 1; }
@@ -307,3 +311,15 @@ VA_Slice_IMP(VArray *self, uint32_t offset, uint32_t length) {
     return slice;
 }
 
+static void
+SI_grow_by(VArray *self, uint32_t add_size) {
+    size_t min_size = self->size + add_size;
+    // Check for overflow.
+    if ((uint32_t)min_size < add_size) {
+        THROW(ERR, "Array grew too large");
+    }
+    size_t new_size = Memory_oversize(min_size, sizeof(Obj*));
+    if (new_size > UINT32_MAX) { new_size = UINT32_MAX; }
+    VA_Grow(self, (uint32_t)new_size);
+}
+