Repository: lucy-clownfish Updated Branches: refs/heads/master 385feba68 -> f8d4b8bed
Make Store and Resize clear excised array elements If elements were removed from an array, the old garbage pointers could become visible again after a Resize or out-of-bounds Store. Make sure that these operations clear all newly accessible elements. This removes the need to clear the end of the buffer after a resize operation. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/f8d4b8be Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/f8d4b8be Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/f8d4b8be Branch: refs/heads/master Commit: f8d4b8bed440406457acb163a29f9412b1116e70 Parents: 385feba Author: Nick Wellnhofer <[email protected]> Authored: Sun Apr 26 13:17:38 2015 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Sun Apr 26 13:26:48 2015 +0200 ---------------------------------------------------------------------- runtime/core/Clownfish/Test/TestVArray.c | 35 ++++++++++++++++++++++++++- runtime/core/Clownfish/VArray.c | 18 ++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f8d4b8be/runtime/core/Clownfish/Test/TestVArray.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Test/TestVArray.c b/runtime/core/Clownfish/Test/TestVArray.c index a509419..64fb808 100644 --- a/runtime/core/Clownfish/Test/TestVArray.c +++ b/runtime/core/Clownfish/Test/TestVArray.c @@ -37,6 +37,21 @@ TestVArray_new() { return (TestVArray*)Class_Make_Obj(TESTVARRAY); } +// Return an array of size 10 with 30 garbage pointers behind. +static VArray* +S_array_with_garbage() { + VArray *array = VA_new(100); + + for (int i = 0; i < 40; i++) { + VA_Push(array, (Obj*)CFISH_TRUE); + } + + // Remove elements using different methods. + VA_Excise(array, 10, 10); + for (int i = 0; i < 10; i++) { VA_Pop(array); } + VA_Resize(array, 10); +} + static void test_Equals(TestBatchRunner *runner) { VArray *array = VA_new(0); @@ -111,6 +126,15 @@ test_Store_Fetch(TestBatchRunner *runner) { TEST_TRUE(runner, Str_Equals_Utf8(elem, "bar", 3), "Store displacement"); DECREF(array); + + array = S_array_with_garbage(); + VA_Store(array, 40, (Obj*)CFISH_TRUE); + bool all_null = true; + for (int i = 10; i < 40; i++) { + if (VA_Fetch(array, i) != NULL) { all_null = false; } + } + TEST_TRUE(runner, all_null, "Out-of-bounds Store clears excised elements"); + DECREF(array); } static void @@ -200,6 +224,15 @@ test_Resize(TestBatchRunner *runner) { TEST_INT_EQ(runner, VA_Get_Size(array), 2, "Resize to same size"); DECREF(array); + + array = S_array_with_garbage(); + VA_Resize(array, 40); + bool all_null = true; + for (int i = 10; i < 40; i++) { + if (VA_Fetch(array, i) != NULL) { all_null = false; } + } + TEST_TRUE(runner, all_null, "Resize clears excised elements"); + DECREF(array); } static void @@ -516,7 +549,7 @@ test_Grow(TestBatchRunner *runner) { void TestVArray_Run_IMP(TestVArray *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 64); + TestBatchRunner_Plan(runner, (TestBatch*)self, 66); test_Equals(runner); test_Store_Fetch(runner); test_Push_Pop_Shift_Unshift(runner); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f8d4b8be/runtime/core/Clownfish/VArray.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/VArray.c b/runtime/core/Clownfish/VArray.c index e3c2240..689032a 100644 --- a/runtime/core/Clownfish/VArray.c +++ b/runtime/core/Clownfish/VArray.c @@ -113,9 +113,7 @@ VA_Push_VArray_IMP(VArray *self, VArray *other) { } for (size_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->elems[tick] = INCREF(elem); } self->size += other->size; } @@ -172,8 +170,14 @@ VA_Store_IMP(VArray *self, size_t tick, Obj *elem) { } SI_grow_by(self, tick + 1 - self->size); } - if (tick < self->size) { DECREF(self->elems[tick]); } - else { self->size = tick + 1; } + if (tick < self->size) { + DECREF(self->elems[tick]); + } + else { + memset(self->elems + self->size, 0, + (tick - self->size) * sizeof(Obj*)); + self->size = tick + 1; + } self->elems[tick] = elem; } @@ -185,8 +189,6 @@ VA_Grow_IMP(VArray *self, size_t capacity) { } self->elems = (Obj**)REALLOCATE(self->elems, capacity * sizeof(Obj*)); self->cap = capacity; - memset(self->elems + self->size, 0, - (capacity - self->size) * sizeof(Obj*)); } } @@ -227,6 +229,8 @@ VA_Resize_IMP(VArray *self, size_t size) { } else if (size > self->size) { VA_Grow(self, size); + memset(self->elems + self->size, 0, + (size - self->size) * sizeof(Obj*)); } self->size = size; }
