summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tree-walk.c28
-rw-r--r--tree-walk.h2
-rw-r--r--unpack-trees.c3
3 files changed, 23 insertions, 10 deletions
diff --git a/tree-walk.c b/tree-walk.c
index c2952f3793..4f1e9d79ab 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -181,21 +181,32 @@ void setup_traverse_info(struct traverse_info *info, const char *base)
info->prev = &dummy;
}
-char *make_traverse_path(char *path, const struct traverse_info *info,
+char *make_traverse_path(char *path, size_t pathlen,
+ const struct traverse_info *info,
const char *name, size_t namelen)
{
- size_t pathlen = info->pathlen;
+ /* Always points to the end of the name we're about to add */
+ size_t pos = st_add(info->pathlen, namelen);
- path[pathlen + namelen] = 0;
+ if (pos >= pathlen)
+ BUG("too small buffer passed to make_traverse_path");
+
+ path[pos] = 0;
for (;;) {
- memcpy(path + pathlen, name, namelen);
- if (!pathlen)
+ if (pos < namelen)
+ BUG("traverse_info pathlen does not match strings");
+ pos -= namelen;
+ memcpy(path + pos, name, namelen);
+
+ if (!pos)
break;
- path[--pathlen] = '/';
+ path[--pos] = '/';
+
+ if (!info)
+ BUG("traverse_info ran out of list items");
name = info->name;
namelen = info->namelen;
info = info->prev;
- pathlen -= namelen;
}
return path;
}
@@ -207,7 +218,8 @@ void strbuf_make_traverse_path(struct strbuf *out,
size_t len = traverse_path_len(info, namelen);
strbuf_grow(out, len);
- make_traverse_path(out->buf + out->len, info, name, namelen);
+ make_traverse_path(out->buf + out->len, out->alloc - out->len,
+ info, name, namelen);
strbuf_setlen(out, out->len + len);
}
diff --git a/tree-walk.h b/tree-walk.h
index 994c14a499..a3ad54e6ce 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -70,7 +70,7 @@ struct traverse_info {
};
int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned short *);
-char *make_traverse_path(char *path, const struct traverse_info *info,
+char *make_traverse_path(char *path, size_t pathlen, const struct traverse_info *info,
const char *name, size_t namelen);
void strbuf_make_traverse_path(struct strbuf *out,
const struct traverse_info *info,
diff --git a/unpack-trees.c b/unpack-trees.c
index c3059c2440..65c4677578 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -968,7 +968,8 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
ce->ce_flags = create_ce_flags(stage);
ce->ce_namelen = len;
oidcpy(&ce->oid, &n->oid);
- make_traverse_path(ce->name, info, n->path, n->pathlen);
+ /* len+1 because the cache_entry allocates space for NUL */
+ make_traverse_path(ce->name, len + 1, info, n->path, n->pathlen);
return ce;
}