Use `size_t` to hold size of arrays Use `size_t` to hold the size of arrays to ease overflow checking, lest we check for overflow of a `size_t` then promptly truncate by packing the length into a smaller type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
diff --git a/src/array.h b/src/array.h
index 0d07953..7c4dbdb 100644
--- a/src/array.h
+++ b/src/array.h
@@ -23,7 +23,7 @@
*
* typedef git_array_t(my_struct) my_struct_array_t;
*/
-#define git_array_t(type) struct { type *ptr; uint32_t size, asize; }
+#define git_array_t(type) struct { type *ptr; size_t size, asize; }
#define GIT_ARRAY_INIT { NULL, 0, 0 }
@@ -45,7 +45,7 @@ typedef git_array_t(char) git_array_generic_t;
GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
{
volatile git_array_generic_t *a = _a;
- uint32_t new_size;
+ size_t new_size;
char *new_array;
if (a->size < 8) {
diff --git a/src/filebuf.c b/src/filebuf.c
index 1a91575..94f2bec 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -408,8 +408,8 @@ int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
int git_filebuf_printf(git_filebuf *file, const char *format, ...)
{
va_list arglist;
- size_t space_left;
- int len, res;
+ size_t space_left, len;
+ int written, res;
char *tmp_buffer;
ENSURE_BUF_OK(file);
@@ -418,15 +418,16 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
do {
va_start(arglist, format);
- len = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
+ written = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
va_end(arglist);
- if (len < 0) {
+ if (written < 0) {
file->last_error = BUFERR_MEM;
return -1;
}
- if ((size_t)len + 1 <= space_left) {
+ len = written;
+ if (len + 1 <= space_left) {
file->buf_pos += len;
return 0;
}
@@ -436,7 +437,7 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
space_left = file->buf_size - file->buf_pos;
- } while ((size_t)len + 1 <= space_left);
+ } while (len + 1 <= space_left);
if (GIT_ALLOC_OVERFLOW_ADD(len, 1) ||
!(tmp_buffer = git__malloc(len + 1))) {
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 2880770..9b56234 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -190,6 +190,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
{
git_pobject *po;
khiter_t pos;
+ size_t newsize;
int ret;
assert(pb && oid);
@@ -203,7 +204,14 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
if (pb->nr_objects >= pb->nr_alloc) {
GITERR_CHECK_ALLOC_ADD(pb->nr_alloc, 1024);
GITERR_CHECK_ALLOC_MULTIPLY(pb->nr_alloc + 1024, 3 / 2);
- pb->nr_alloc = (pb->nr_alloc + 1024) * 3 / 2;
+ newsize = (pb->nr_alloc + 1024) * 3 / 2;
+
+ if (!git__is_uint32(newsize)) {
+ giterr_set(GITERR_NOMEMORY, "Packfile too large to fit in memory.");
+ return -1;
+ }
+
+ pb->nr_alloc = (uint32_t)newsize;
pb->object_list = git__reallocarray(pb->object_list,
pb->nr_alloc, sizeof(*po));
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index ad81ad1..11c6215 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -484,7 +484,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
{
git_buf str = GIT_BUF_INIT;
char oid[GIT_OID_HEXSZ +1] = {0};
- unsigned int len;
+ size_t len;
/* Prefer multi_ack_detailed */
if (caps->multi_ack_detailed)
@@ -510,12 +510,19 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
if (git_buf_oom(&str))
return -1;
- len = (unsigned int)
- (strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
- git_buf_len(&str) + 1 /* LF */);
+ len = strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
+ git_buf_len(&str) + 1 /* LF */;
+
+ if (len > 0xffff) {
+ giterr_set(GITERR_NET,
+ "Tried to produce packet with invalid length %d", len);
+ return -1;
+ }
+
git_buf_grow_by(buf, len);
git_oid_fmt(oid, &head->oid);
- git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str));
+ git_buf_printf(buf,
+ "%04xwant %s %s\n", (unsigned int)len, oid, git_buf_cstr(&str));
git_buf_free(&str);
return git_buf_oom(buf);