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