* [PATCH 0/2] Directory traversal fixes
@ 2021-05-27 4:53 Elijah Newren via GitGitGadget
2021-05-27 4:53 ` [PATCH 1/2] dir: update stale description of treat_directory() Derrick Stolee via GitGitGadget
2021-05-27 4:53 ` [PATCH 2/2] dir: introduce readdir_skip_dot_and_dotdot() helper Elijah Newren via GitGitGadget
0 siblings, 2 replies; 3+ messages in thread
From: Elijah Newren via GitGitGadget @ 2021-05-27 4:53 UTC (permalink / raw)
To: git; +Cc: Elijah Newren
This is a resend of the final two patches of my series, as per
https://lore.kernel.org/git/xmqqfsyht49j.fsf@gitster.g/. It will not merge
cleanly unless the last two patches of en/dir-traversal-fixes are first
reverted, as Junio suggested he'd be doing.
(Corrected Reviewed-by -> Signed-off-by in the first patch, minor stylistic
fix for the second.)
Derrick Stolee (1):
dir: update stale description of treat_directory()
Elijah Newren (1):
dir: introduce readdir_skip_dot_and_dotdot() helper
builtin/clean.c | 4 +---
builtin/worktree.c | 4 +---
diff-no-index.c | 5 ++---
dir.c | 38 ++++++++++++++++++++++----------------
dir.h | 2 ++
entry.c | 5 +----
notes-merge.c | 5 +----
object-file.c | 4 +---
packfile.c | 5 +----
rerere.c | 4 +---
worktree.c | 12 +++---------
11 files changed, 36 insertions(+), 52 deletions(-)
base-commit: dd55fc0df15c338a8dbec6dec6ca6b58edc8acef
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-961%2Fnewren%2Fdirectory-traversal-fixes-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-961/newren/directory-traversal-fixes-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/961
--
gitgitgadget
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] dir: update stale description of treat_directory()
2021-05-27 4:53 [PATCH 0/2] Directory traversal fixes Elijah Newren via GitGitGadget
@ 2021-05-27 4:53 ` Derrick Stolee via GitGitGadget
2021-05-27 4:53 ` [PATCH 2/2] dir: introduce readdir_skip_dot_and_dotdot() helper Elijah Newren via GitGitGadget
1 sibling, 0 replies; 3+ messages in thread
From: Derrick Stolee via GitGitGadget @ 2021-05-27 4:53 UTC (permalink / raw)
To: git; +Cc: Elijah Newren, Derrick Stolee
From: Derrick Stolee <stolee@gmail.com>
The documentation comment for treat_directory() was originally written
in 095952 (Teach directory traversal about subprojects, 2007-04-11)
which was before the 'struct dir_struct' split its bitfield of named
options into a 'flags' enum in 7c4c97c0 (Turn the flags in struct
dir_struct into a single variable, 2009-02-16). When those flags
changed, the comment became stale, since members like
'show_other_directories' transitioned into flags like
DIR_SHOW_OTHER_DIRECTORIES.
Update the comments for treat_directory() to use these flag names rather
than the old member names.
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
---
dir.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/dir.c b/dir.c
index ed68b7e6412c..ff004b298b2a 100644
--- a/dir.c
+++ b/dir.c
@@ -1740,13 +1740,13 @@ static enum exist_status directory_exists_in_index(struct index_state *istate,
* Case 3: if we didn't have it in the index previously, we
* have a few sub-cases:
*
- * (a) if "show_other_directories" is true, we show it as
- * just a directory, unless "hide_empty_directories" is
+ * (a) if DIR_SHOW_OTHER_DIRECTORIES flag is set, we show it as
+ * just a directory, unless DIR_HIDE_EMPTY_DIRECTORIES is
* also true, in which case we need to check if it contains any
* untracked and / or ignored files.
- * (b) if it looks like a git directory, and we don't have
- * 'no_gitlinks' set we treat it as a gitlink, and show it
- * as a directory.
+ * (b) if it looks like a git directory and we don't have the
+ * DIR_NO_GITLINKS flag, then we treat it as a gitlink, and
+ * show it as a directory.
* (c) otherwise, we recurse into it.
*/
static enum path_treatment treat_directory(struct dir_struct *dir,
@@ -1834,7 +1834,6 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
return path_recurse;
}
- /* This is the "show_other_directories" case */
assert(dir->flags & DIR_SHOW_OTHER_DIRECTORIES);
/*
@@ -1849,7 +1848,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
/* Special cases for where this directory is excluded/ignored */
if (excluded) {
/*
- * In the show_other_directories case, if we're not
+ * If DIR_SHOW_OTHER_DIRECTORIES is set and we're not
* hiding empty directories, there is no need to
* recurse into an ignored directory.
*/
--
gitgitgadget
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] dir: introduce readdir_skip_dot_and_dotdot() helper
2021-05-27 4:53 [PATCH 0/2] Directory traversal fixes Elijah Newren via GitGitGadget
2021-05-27 4:53 ` [PATCH 1/2] dir: update stale description of treat_directory() Derrick Stolee via GitGitGadget
@ 2021-05-27 4:53 ` Elijah Newren via GitGitGadget
1 sibling, 0 replies; 3+ messages in thread
From: Elijah Newren via GitGitGadget @ 2021-05-27 4:53 UTC (permalink / raw)
To: git; +Cc: Elijah Newren, Elijah Newren
From: Elijah Newren <newren@gmail.com>
Many places in the code were doing
while ((d = readdir(dir)) != NULL) {
if (is_dot_or_dotdot(d->d_name))
continue;
...process d...
}
Introduce a readdir_skip_dot_and_dotdot() helper to make that a one-liner:
while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
...process d...
}
This helper particularly simplifies checks for empty directories.
Also use this helper in read_cached_dir() so that our statistics are
consistent across platforms. (In other words, read_cached_dir() should
have been using is_dot_or_dotdot() and skipping such entries, but did
not and left it to treat_path() to detect and mark such entries as
path_none.)
Signed-off-by: Elijah Newren <newren@gmail.com>
---
builtin/clean.c | 4 +---
builtin/worktree.c | 4 +---
diff-no-index.c | 5 ++---
dir.c | 25 ++++++++++++++++---------
dir.h | 2 ++
entry.c | 5 +----
notes-merge.c | 5 +----
object-file.c | 4 +---
packfile.c | 5 +----
rerere.c | 4 +---
worktree.c | 12 +++---------
11 files changed, 30 insertions(+), 45 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 995053b79173..a1a57476153b 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -189,10 +189,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
strbuf_complete(path, '/');
len = path->len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(e->d_name))
- continue;
strbuf_setlen(path, len);
strbuf_addstr(path, e->d_name);
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 1cd5c2016e3f..e081ca9befd1 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -118,10 +118,8 @@ static void prune_worktrees(void)
struct dirent *d;
if (!dir)
return;
- while ((d = readdir(dir)) != NULL) {
+ while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
char *path;
- if (is_dot_or_dotdot(d->d_name))
- continue;
strbuf_reset(&reason);
if (should_prune_worktree(d->d_name, &reason, &path, expire))
prune_worktree(d->d_name, reason.buf);
diff --git a/diff-no-index.c b/diff-no-index.c
index 7814eabfe028..e5cc87837143 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -26,9 +26,8 @@ static int read_directory_contents(const char *path, struct string_list *list)
if (!(dir = opendir(path)))
return error("Could not open directory %s", path);
- while ((e = readdir(dir)))
- if (!is_dot_or_dotdot(e->d_name))
- string_list_insert(list, e->d_name);
+ while ((e = readdir_skip_dot_and_dotdot(dir)))
+ string_list_insert(list, e->d_name);
closedir(dir);
return 0;
diff --git a/dir.c b/dir.c
index ff004b298b2a..b909cf9b03da 100644
--- a/dir.c
+++ b/dir.c
@@ -59,6 +59,17 @@ void dir_init(struct dir_struct *dir)
memset(dir, 0, sizeof(*dir));
}
+struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
+{
+ struct dirent *e;
+
+ while ((e = readdir(dirp)) != NULL) {
+ if (!is_dot_or_dotdot(e->d_name))
+ break;
+ }
+ return e;
+}
+
int count_slashes(const char *s)
{
int cnt = 0;
@@ -2332,7 +2343,7 @@ static int read_cached_dir(struct cached_dir *cdir)
struct dirent *de;
if (cdir->fdir) {
- de = readdir(cdir->fdir);
+ de = readdir_skip_dot_and_dotdot(cdir->fdir);
if (!de) {
cdir->d_name = NULL;
cdir->d_type = DT_UNKNOWN;
@@ -2931,11 +2942,9 @@ int is_empty_dir(const char *path)
if (!dir)
return 0;
- while ((e = readdir(dir)) != NULL)
- if (!is_dot_or_dotdot(e->d_name)) {
- ret = 0;
- break;
- }
+ e = readdir_skip_dot_and_dotdot(dir);
+ if (e)
+ ret = 0;
closedir(dir);
return ret;
@@ -2975,10 +2984,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
strbuf_complete(path, '/');
len = path->len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(e->d_name))
- continue;
strbuf_setlen(path, len);
strbuf_addstr(path, e->d_name);
diff --git a/dir.h b/dir.h
index 70c750e3053d..6b3fac082945 100644
--- a/dir.h
+++ b/dir.h
@@ -342,6 +342,8 @@ struct dir_struct {
unsigned visited_directories;
};
+struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp);
+
/*Count the number of slashes for string s*/
int count_slashes(const char *s);
diff --git a/entry.c b/entry.c
index 7b9f43716f76..e3d3add30007 100644
--- a/entry.c
+++ b/entry.c
@@ -56,12 +56,9 @@ static void remove_subtree(struct strbuf *path)
if (!dir)
die_errno("cannot opendir '%s'", path->buf);
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(de->d_name))
- continue;
-
strbuf_addch(path, '/');
strbuf_addstr(path, de->d_name);
if (lstat(path->buf, &st))
diff --git a/notes-merge.c b/notes-merge.c
index d2771fa3d43c..e9d6f86d3428 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -695,13 +695,10 @@ int notes_merge_commit(struct notes_merge_options *o,
strbuf_addch(&path, '/');
baselen = path.len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
struct object_id obj_oid, blob_oid;
- if (is_dot_or_dotdot(e->d_name))
- continue;
-
if (get_oid_hex(e->d_name, &obj_oid)) {
if (o->verbosity >= 3)
printf("Skipping non-SHA1 entry '%s%s'\n",
diff --git a/object-file.c b/object-file.c
index 624af408cdcd..77bdcfd21bc8 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2304,10 +2304,8 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
strbuf_addch(path, '/');
baselen = path->len;
- while ((de = readdir(dir))) {
+ while ((de = readdir_skip_dot_and_dotdot(dir))) {
size_t namelen;
- if (is_dot_or_dotdot(de->d_name))
- continue;
namelen = strlen(de->d_name);
strbuf_setlen(path, baselen);
diff --git a/packfile.c b/packfile.c
index ea29f4ba7735..463d61c87761 100644
--- a/packfile.c
+++ b/packfile.c
@@ -813,10 +813,7 @@ void for_each_file_in_pack_dir(const char *objdir,
}
strbuf_addch(&path, '/');
dirnamelen = path.len;
- while ((de = readdir(dir)) != NULL) {
- if (is_dot_or_dotdot(de->d_name))
- continue;
-
+ while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
strbuf_setlen(&path, dirnamelen);
strbuf_addstr(&path, de->d_name);
diff --git a/rerere.c b/rerere.c
index dee60dc6df63..d83d58df4fbc 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1190,13 +1190,11 @@ void rerere_gc(struct repository *r, struct string_list *rr)
if (!dir)
die_errno(_("unable to open rr-cache directory"));
/* Collect stale conflict IDs ... */
- while ((e = readdir(dir))) {
+ while ((e = readdir_skip_dot_and_dotdot(dir))) {
struct rerere_dir *rr_dir;
struct rerere_id id;
int now_empty;
- if (is_dot_or_dotdot(e->d_name))
- continue;
if (!is_rr_cache_dirname(e->d_name))
continue; /* or should we remove e->d_name? */
diff --git a/worktree.c b/worktree.c
index f35ac40a84a5..237517baee67 100644
--- a/worktree.c
+++ b/worktree.c
@@ -128,10 +128,8 @@ struct worktree **get_worktrees(void)
dir = opendir(path.buf);
strbuf_release(&path);
if (dir) {
- while ((d = readdir(dir)) != NULL) {
+ while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct worktree *linked = NULL;
- if (is_dot_or_dotdot(d->d_name))
- continue;
if ((linked = get_linked_worktree(d->d_name))) {
ALLOC_GROW(list, counter + 1, alloc);
@@ -486,13 +484,9 @@ int submodule_uses_worktrees(const char *path)
if (!dir)
return 0;
- while ((d = readdir(dir)) != NULL) {
- if (is_dot_or_dotdot(d->d_name))
- continue;
-
+ d = readdir_skip_dot_and_dotdot(dir);
+ if (d != NULL)
ret = 1;
- break;
- }
closedir(dir);
return ret;
}
--
gitgitgadget
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-05-27 4:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-27 4:53 [PATCH 0/2] Directory traversal fixes Elijah Newren via GitGitGadget
2021-05-27 4:53 ` [PATCH 1/2] dir: update stale description of treat_directory() Derrick Stolee via GitGitGadget
2021-05-27 4:53 ` [PATCH 2/2] dir: introduce readdir_skip_dot_and_dotdot() helper Elijah Newren via GitGitGadget
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).