diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-01-18 23:42:00 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-21 12:44:31 -0800 |
commit | 7fec10b7f41fa32e71aa6377bd04cd7c6fb419e0 (patch) | |
tree | 29820d183e9b379d3aacc4757e4a7ea98c3247a3 /read-cache.c | |
parent | 7a51ed66f653c248993b3c4a61932e47933d835e (diff) | |
download | git-7fec10b7f41fa32e71aa6377bd04cd7c6fb419e0.tar.gz |
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 <gitster@pobox.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/read-cache.c b/read-cache.c index 82a6238b77..528f697f59 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! */ |