summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-10-29 13:59:19 -0700
committerJunio C Hamano <gitster@pobox.com>2015-10-29 13:59:19 -0700
commit69fe31887bf8be496bb0adb4db3150cec52e1a2c (patch)
tree4e9040a5fa5d0fe7ae4b62ab11c6b55723b77f4c /dir.c
parent433cc7e3fb861d4530ca6c49b152e94219bddfda (diff)
parent41284eb0f944fe2d73708bb4105a8e3ccd0297df (diff)
downloadgit-69fe31887bf8be496bb0adb4db3150cec52e1a2c.tar.gz
Merge branch 'dt/name-hash-dir-entry-fix'
The name-hash subsystem that is used to cope with case insensitive filesystems keeps track of directories and their on-filesystem cases for all the paths in the index by holding a pointer to a randomly chosen cache entry that is inside the directory (for its ce->ce_name component). This pointer was not updated even when the cache entry was removed from the index, leading to use after free. This was fixed by recording the path for each directory instead of borrowing cache entries and restructuring the API somewhat. * dt/name-hash-dir-entry-fix: name-hash: don't reuse cache_entry in dir_entry
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c22
1 files changed, 4 insertions, 18 deletions
diff --git a/dir.c b/dir.c
index 109ceeaed3..d2a8f06b02 100644
--- a/dir.c
+++ b/dir.c
@@ -1279,29 +1279,15 @@ enum exist_status {
*/
static enum exist_status directory_exists_in_index_icase(const char *dirname, int len)
{
- const struct cache_entry *ce = cache_dir_exists(dirname, len);
- unsigned char endchar;
+ struct cache_entry *ce;
- if (!ce)
- return index_nonexistent;
- endchar = ce->name[len];
-
- /*
- * The cache_entry structure returned will contain this dirname
- * and possibly additional path components.
- */
- if (endchar == '/')
+ if (cache_dir_exists(dirname, len))
return index_directory;
- /*
- * If there are no additional path components, then this cache_entry
- * represents a submodule. Submodules, despite being directories,
- * are stored in the cache without a closing slash.
- */
- if (!endchar && S_ISGITLINK(ce->ce_mode))
+ ce = cache_file_exists(dirname, len, ignore_case);
+ if (ce && S_ISGITLINK(ce->ce_mode))
return index_gitdir;
- /* This should never be hit, but it exists just in case. */
return index_nonexistent;
}