summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Budovski <abudovski@gmail.com>2011-01-07 11:35:43 +1100
committerVicent Marti <tanoku@gmail.com>2011-01-08 22:17:52 +0200
commita17777d161583401983a6dc1e5a659c9dc2f5257 (patch)
tree3f74aa73efdde83205a2938a05dc9cf15ff27a50
parent9ace34c8deb97cb18aafe6bf2aa4a6b69dd5f117 (diff)
downloadlibgit2-a17777d161583401983a6dc1e5a659c9dc2f5257.tar.gz
Fixed two buffer handling errors in vector.c
- remove() would read one-past array bounds. - resize() would fail if the initial size was 1, because it multiplied by 1.75 and truncated the resulting value. The buffer would always remain at size 1, but elements would repeatedly be appended (via insert()) causing a crash.
-rw-r--r--src/vector.c4
-rw-r--r--tests/t0004-vector.c27
2 files changed, 29 insertions, 2 deletions
diff --git a/src/vector.c b/src/vector.c
index 47e8ce845..325f34306 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -34,7 +34,7 @@ static int resize_vector(git_vector *v)
{
void **new_contents;
- v->_alloc_size = (unsigned int)(v->_alloc_size * resize_factor);
+ v->_alloc_size = ((unsigned int)(v->_alloc_size * resize_factor)) + 1;
if (v->_alloc_size == 0)
v->_alloc_size = minimum_size;
@@ -130,7 +130,7 @@ int git_vector_remove(git_vector *v, unsigned int idx)
if (idx >= v->length || v->length == 0)
return GIT_ENOTFOUND;
- for (i = idx; i < v->length; ++i)
+ for (i = idx; i < v->length - 1; ++i)
v->contents[i] = v->contents[i + 1];
v->length--;
diff --git a/tests/t0004-vector.c b/tests/t0004-vector.c
new file mode 100644
index 000000000..bee71d2f2
--- /dev/null
+++ b/tests/t0004-vector.c
@@ -0,0 +1,27 @@
+#include "test_lib.h"
+#include "common.h"
+#include "vector.h"
+
+/* Initial size of 1 will cause writing past array bounds prior to fix */
+BEGIN_TEST(initial_size_one)
+ git_vector x;
+ int i;
+ git_vector_init(&x, 1, NULL, NULL);
+ for (i = 0; i < 10; ++i) {
+ git_vector_insert(&x, (void*) 0xabc);
+ }
+ git_vector_free(&x);
+END_TEST
+
+/* vector used to read past array bounds on remove() */
+BEGIN_TEST(remove)
+ git_vector x;
+ // make initial capacity exact for our insertions.
+ git_vector_init(&x, 3, NULL, NULL);
+ git_vector_insert(&x, (void*) 0xabc);
+ git_vector_insert(&x, (void*) 0xdef);
+ git_vector_insert(&x, (void*) 0x123);
+
+ git_vector_remove(&x, 0); // used to read past array bounds.
+ git_vector_free(&x);
+END_TEST