tree-walk: use size_t consistently

We store and manipulate the cumulative traverse_info.pathlen as an "int", which can overflow when we are fed ridiculously long pathnames (e.g., ones at the edge of 2GB or 4GB, even if the individual tree entry names are smaller than that). The results can be confusing, though after some prodding I was not able to use this integer overflow to cause an under-allocated buffer. Let's consistently use size_t to generate and store these, and make sure our addition doesn't overflow. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 31, 2019 at 00:38 UTC 37806080d7be1ab5b2fa918f6a528652596ea2c1
3 files changed +8 -8
tree-walk.c
+2 -2
@@ -168,7 +168,7 @@ int tree_entry_gently(struct tree_desc *desc, struct name_entry *entry)
168
169 void setup_traverse_info(struct traverse_info *info, const char *base)
170 {
171 - int pathlen = strlen(base);
171 + size_t pathlen = strlen(base);
172 static struct traverse_info dummy;
173
174 memset(info, 0, sizeof(*info));
@@ -184,7 +184,7 @@ void setup_traverse_info(struct traverse_info *info, const char *base)
184 char *make_traverse_path(char *path, const struct traverse_info *info,
185 const char *name, size_t namelen)
186 {
187 - int pathlen = info->pathlen;
187 + size_t pathlen = info->pathlen;
188
189 path[pathlen + namelen] = 0;
190 for (;;) {
tree-walk.h
+3 -3
@@ -60,7 +60,7 @@ struct traverse_info {
60 size_t namelen;
61 unsigned mode;
62
63 - int pathlen;
63 + size_t pathlen;
64 struct pathspec *pathspec;
65
66 unsigned long df_conflicts;
@@ -74,9 +74,9 @@ char *make_traverse_path(char *path, const struct traverse_info *info,
74 const char *name, size_t namelen);
75 void setup_traverse_info(struct traverse_info *info, const char *base);
76
77 -static inline int traverse_path_len(const struct traverse_info *info, const struct name_entry *n)
77 +static inline size_t traverse_path_len(const struct traverse_info *info, const struct name_entry *n)
78 {
79 - return info->pathlen + tree_entry_len(n);
79 + return st_add(info->pathlen, tree_entry_len(n));
80 }
81
82 /* in general, positive means "kind of interesting" */
unpack-trees.c
+3 -3
@@ -686,7 +686,7 @@ static int index_pos_by_traverse_info(struct name_entry *names,
686 struct traverse_info *info)
687 {
688 struct unpack_trees_options *o = info->data;
689 - int len = traverse_path_len(info, names);
689 + size_t len = traverse_path_len(info, names);
690 char *name = xmalloc(len + 1 /* slash */ + 1 /* NUL */);
691 int pos;
692
@@ -814,7 +814,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
814 newinfo.name = p->path;
815 newinfo.namelen = p->pathlen;
816 newinfo.mode = p->mode;
817 - newinfo.pathlen += tree_entry_len(p) + 1;
817 + newinfo.pathlen = st_add3(newinfo.pathlen, tree_entry_len(p), 1);
818 newinfo.df_conflicts |= df_conflicts;
819
820 /*
@@ -960,7 +960,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
960 struct index_state *istate,
961 int is_transient)
962 {
963 - int len = traverse_path_len(info, n);
963 + size_t len = traverse_path_len(info, n);
964 struct cache_entry *ce =
965 is_transient ?
966 make_empty_transient_cache_entry(len) :