path: root/read-cache.c
diff options
authorJunio C Hamano <>2008-01-19 07:42:00 (GMT)
committerLinus Torvalds <>2008-01-21 20:44:31 (GMT)
commit7fec10b7f41fa32e71aa6377bd04cd7c6fb419e0 (patch)
tree29820d183e9b379d3aacc4757e4a7ea98c3247a3 /read-cache.c
parent7a51ed66f653c248993b3c4a61932e47933d835e (diff)
index: be careful when handling long names
We currently use lower 12-bit (masked with CE_NAMEMASK) in the ce_flags field to store the length of the name in cache_entry, without checking the length parameter given to create_ce_flags(). This can make us store incorrect length. Currently we are mostly protected by the fact that many codepaths first copy the path in a variable of size PATH_MAX, which typically is 4096 that happens to match the limit, but that feels like a bug waiting to happen. Besides, that would not allow us to shorten the width of CE_NAMEMASK to use the bits for new flags. This redefines the meaning of the name length stored in the cache_entry. A name that does not fit is represented by storing CE_NAMEMASK in the field, and the actual length needs to be computed by actually counting the bytes in the name[] field. This way, only the unusually long paths need to suffer. Signed-off-by: Junio C Hamano <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'read-cache.c')
1 files changed, 11 insertions, 1 deletions
diff --git a/read-cache.c b/read-cache.c
index 82a6238..528f697 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -928,6 +928,8 @@ int read_index(struct index_state *istate)
static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce)
+ size_t len;
ce->ce_ctime = ntohl(ondisk->ctime.sec);
ce->ce_mtime = ntohl(ondisk->mtime.sec);
ce->ce_dev = ntohl(ondisk->dev);
@@ -939,7 +941,15 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
/* On-disk flags are just 16 bits */
ce->ce_flags = ntohs(ondisk->flags);
hashcpy(ce->sha1, ondisk->sha1);
- memcpy(ce->name, ondisk->name, ce_namelen(ce)+1);
+ len = ce->ce_flags & CE_NAMEMASK;
+ if (len == CE_NAMEMASK)
+ len = strlen(ondisk->name);
+ /*
+ * NEEDSWORK: If the original index is crafted, this copy could
+ * go unchecked.
+ */
+ memcpy(ce->name, ondisk->name, len + 1);
/* remember to discard_cache() before reading a different cache! */