summaryrefslogtreecommitdiff
path: root/src/vector.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-09-25 12:41:15 -0400
committerEdward Thomson <ethomson@github.com>2016-05-26 13:01:07 -0500
commite564fc65b53b67ff0753749caa07b7877fb22420 (patch)
treeacf4564f4c4bfe65d26a543f7727c3dbf99e0055 /src/vector.c
parent0ff723cc90c258f2b78285e7e4b55352e1bc05cd (diff)
downloadlibgit2-e564fc65b53b67ff0753749caa07b7877fb22420.tar.gz
git_vector_grow/shrink: correct shrink, and tests
Diffstat (limited to 'src/vector.c')
-rw-r--r--src/vector.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/src/vector.c b/src/vector.c
index 368467692..5ad8a738c 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -7,6 +7,7 @@
#include "common.h"
#include "vector.h"
+#include "integer.h"
/* In elements, not bytes */
#define MIN_ALLOCSIZE 8
@@ -332,17 +333,16 @@ int git_vector_resize_to(git_vector *v, size_t new_length)
int git_vector_grow_at(git_vector *v, size_t idx, size_t grow_len)
{
- size_t new_length = v->length + grow_len;
- size_t new_idx = idx + grow_len;
+ size_t new_length;
- assert(grow_len > 0);
- assert (idx <= v->length);
+ assert(grow_len > 0 && idx <= v->length);
- if (new_length < v->length ||
- (new_length > v->_alloc_size && resize_vector(v, new_length) < 0))
+ GITERR_CHECK_ALLOC_ADD(&new_length, v->length, grow_len);
+
+ if (new_length > v->_alloc_size && resize_vector(v, new_length) < 0)
return -1;
- memmove(&v->contents[new_idx], &v->contents[idx],
+ memmove(&v->contents[idx + grow_len], &v->contents[idx],
sizeof(void *) * (v->length - idx));
memset(&v->contents[idx], 0, sizeof(void *) * grow_len);
@@ -353,17 +353,18 @@ int git_vector_grow_at(git_vector *v, size_t idx, size_t grow_len)
int git_vector_shrink_at(git_vector *v, size_t idx, size_t shrink_len)
{
size_t new_length = v->length - shrink_len;
- size_t end_idx = idx + shrink_len;
+ size_t end_idx = 0;
+
+ assert(shrink_len > 0);
- assert(shrink_len > 0 && shrink_len <= v->length);
- assert(idx <= v->length);
+ if (git__add_sizet_overflow(&end_idx, idx, shrink_len))
+ assert(0);
- if (new_length > v->length)
- return -1;
+ assert(end_idx <= v->length);
- if (idx > v->length)
+ if (end_idx < v->length)
memmove(&v->contents[idx], &v->contents[end_idx],
- sizeof(void *) * (v->length - idx));
+ sizeof(void *) * (v->length - end_idx));
memset(&v->contents[new_length], 0, sizeof(void *) * shrink_len);