diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-04-04 19:59:57 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2021-04-28 13:03:34 +0100 |
commit | 9fb755d561e149b81950c7cc7d8cb5131b24079b (patch) | |
tree | e242de6ecdd0e2a5ce3d00aab2debef535063a4f /src | |
parent | e52c2989fb6911ef74cccd87a57bffd884842d36 (diff) | |
download | libgit2-9fb755d561e149b81950c7cc7d8cb5131b24079b.tar.gz |
attr: validate workdir paths for attribute files
We should allow attribute files - inside working directories - to have
names longer than MAX_PATH when core.longpaths is set.
`git_attr_path__init` takes a repository to validate the path with.
Diffstat (limited to 'src')
-rw-r--r-- | src/attr.c | 6 | ||||
-rw-r--r-- | src/attr_file.c | 11 | ||||
-rw-r--r-- | src/attr_file.h | 7 | ||||
-rw-r--r-- | src/attrcache.c | 11 | ||||
-rw-r--r-- | src/attrcache.h | 1 | ||||
-rw-r--r-- | src/ignore.c | 4 |
6 files changed, 27 insertions, 13 deletions
diff --git a/src/attr.c b/src/attr.c index e85e27162..f9cd93074 100644 --- a/src/attr.c +++ b/src/attr.c @@ -67,7 +67,7 @@ int git_attr_get( if (git_repository_is_bare(repo)) dir_flag = GIT_DIR_FLAG_FALSE; - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0) + if (git_attr_path__init(&path, repo, pathname, git_repository_workdir(repo), dir_flag) < 0) return -1; if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0) @@ -133,7 +133,7 @@ int git_attr_get_many_with_session( if (git_repository_is_bare(repo)) dir_flag = GIT_DIR_FLAG_FALSE; - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0) + if (git_attr_path__init(&path, repo, pathname, git_repository_workdir(repo), dir_flag) < 0) return -1; if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0) @@ -217,7 +217,7 @@ int git_attr_foreach( if (git_repository_is_bare(repo)) dir_flag = GIT_DIR_FLAG_FALSE; - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0) + if (git_attr_path__init(&path, repo, pathname, git_repository_workdir(repo), dir_flag) < 0) return -1; if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 || diff --git a/src/attr_file.c b/src/attr_file.c index adc56d53e..d1b90c5ba 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -403,7 +403,7 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path) if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 || (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 || - (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0) + (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, NULL, path, &file->pool)) < 0) goto out; *out = file; @@ -503,14 +503,19 @@ git_attr_assignment *git_attr_rule__lookup_assignment( } int git_attr_path__init( - git_attr_path *info, const char *path, const char *base, git_dir_flag dir_flag) + git_attr_path *info, + git_repository *repo, + const char *path, + const char *base, + git_dir_flag dir_flag) { ssize_t root; /* build full path as best we can */ git_buf_init(&info->full, 0); - if (git_path_join_unrooted(&info->full, path, base, &root) < 0) + if (git_path_join_unrooted(&info->full, path, base, &root) < 0 || + git_path_validate_workdir_buf(repo, &info->full) < 0) return -1; info->path = info->full.ptr + root; diff --git a/src/attr_file.h b/src/attr_file.h index 2b6b1d623..617436b14 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -207,8 +207,11 @@ extern git_attr_assignment *git_attr_rule__lookup_assignment( typedef enum { GIT_DIR_FLAG_TRUE = 1, GIT_DIR_FLAG_FALSE = 0, GIT_DIR_FLAG_UNKNOWN = -1 } git_dir_flag; extern int git_attr_path__init( - git_attr_path *info, const char *path, const char *base, git_dir_flag is_dir); - + git_attr_path *out, + git_repository *repo, + const char *path, + const char *base, + git_dir_flag is_dir); extern void git_attr_path__free(git_attr_path *info); extern int git_attr_assignment__parse( diff --git a/src/attrcache.c b/src/attrcache.c index 2485b0599..32513da01 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -38,6 +38,7 @@ GIT_INLINE(git_attr_file_entry *) attr_cache_lookup_entry( int git_attr_cache__alloc_file_entry( git_attr_file_entry **out, + git_repository *repo, const char *base, const char *path, git_pool *pool) @@ -65,6 +66,9 @@ int git_attr_cache__alloc_file_entry( } memcpy(&ce->fullpath[baselen], path, pathlen); + if (git_path_validate_workdir_with_len(repo, ce->fullpath, pathlen + baselen) < 0) + return -1; + ce->path = &ce->fullpath[baselen]; *out = ce; @@ -79,8 +83,8 @@ static int attr_cache_make_entry( git_attr_file_entry *entry = NULL; int error; - if ((error = git_attr_cache__alloc_file_entry(&entry, git_repository_workdir(repo), - path, &cache->pool)) < 0) + if ((error = git_attr_cache__alloc_file_entry(&entry, repo, + git_repository_workdir(repo), path, &cache->pool)) < 0) return error; if ((error = git_strmap_set(cache->files, entry->path, entry)) < 0) @@ -169,7 +173,8 @@ static int attr_cache_lookup( if (base != NULL && git_path_root(filename) < 0) { git_buf *p = attr_session ? &attr_session->tmp : &path; - if (git_buf_joinpath(p, base, filename) < 0) + if (git_buf_joinpath(p, base, filename) < 0 || + git_path_validate_workdir_buf(repo, p) < 0) return -1; filename = p->ptr; diff --git a/src/attrcache.h b/src/attrcache.h index 4b1d5ce31..5e2fb29f4 100644 --- a/src/attrcache.h +++ b/src/attrcache.h @@ -44,6 +44,7 @@ extern bool git_attr_cache__is_cached( extern int git_attr_cache__alloc_file_entry( git_attr_file_entry **out, + git_repository *repo, const char *base, const char *path, git_pool *pool); diff --git a/src/ignore.c b/src/ignore.c index 27a650b1b..085b0e981 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -453,7 +453,7 @@ int git_ignore__lookup( *out = GIT_IGNORE_NOTFOUND; if (git_attr_path__init( - &path, pathname, git_repository_workdir(ignores->repo), dir_flag) < 0) + &path, ignores->repo, pathname, git_repository_workdir(ignores->repo), dir_flag) < 0) return -1; /* first process builtins - success means path was found */ @@ -537,7 +537,7 @@ int git_ignore_path_is_ignored( else if (git_repository_is_bare(repo)) dir_flag = GIT_DIR_FLAG_FALSE; - if ((error = git_attr_path__init(&path, pathname, workdir, dir_flag)) < 0 || + if ((error = git_attr_path__init(&path, repo, pathname, workdir, dir_flag)) < 0 || (error = git_ignore__for_path(repo, path.path, &ignores)) < 0) goto cleanup; |