Re: [PATCH v2 6/8] dir: fix checks on common prefix directory
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Dec 15, 2019, 10:29 UTC
- Message-ID
- <nycvar.QRO.7.76.6.1912151126030.46@tvgsbejvaqbjf.bet>
- In-Reply-To
- <9839aca00a10b16d96c47db631ac025281ffc864.1576008027.git.gitgitgadget@gmail.com>
Hi Elijah,
I have not had time to dive deeply into this, but I know that it _does_ cause a ton of segmentation faults in the `shears/pu` branch (where all of Git for Windows' patches are rebased on top of `pu`):
On Tue, 10 Dec 2019, Elijah Newren via GitGitGadget wrote:
Show 41 quoted lines
> diff --git a/dir.c b/dir.c
> index 645b44ea64..9c71a9ac21 100644
> --- a/dir.c
> +++ b/dir.c
> @@ -2102,37 +2102,69 @@ static int treat_leading_path(struct dir_struct *dir,
> const struct pathspec *pathspec)
> {
> struct strbuf sb = STRBUF_INIT;
> - int baselen, rc = 0;
> + int prevlen, baselen;
> const char *cp;
> + struct cached_dir cdir;
> + struct dirent de;
> + enum path_treatment state = path_none;
> +
> + /*
> + * For each directory component of path, we are going to check whether
> + * that path is relevant given the pathspec. For example, if path is
> + * foo/bar/baz/
> + * then we will ask treat_path() whether we should go into foo, then
> + * whether we should go into bar, then whether baz is relevant.
> + * Checking each is important because e.g. if path is
> + * .git/info/
> + * then we need to check .git to know we shouldn't traverse it.
> + * If the return from treat_path() is:
> + * * path_none, for any path, we return false.
> + * * path_recurse, for all path components, we return true
> + * * <anything else> for some intermediate component, we make sure
> + * to add that path to the relevant list but return false
> + * signifying that we shouldn't recurse into it.
> + */
>
> while (len && path[len - 1] == '/')
> len--;
> if (!len)
> return 1;
> +
> + memset(&cdir, 0, sizeof(cdir));
> + memset(&de, 0, sizeof(de));
> + cdir.de = &de;
> + de.d_type = DT_DIR;So here, `de` is zeroed out, and therefore `de.d_name` is `NULL`.
Show 23 quoted lines
> baselen = 0;
> + prevlen = 0;
> while (1) {
> - cp = path + baselen + !!baselen;
> + prevlen = baselen + !!baselen;
> + cp = path + prevlen;
> cp = memchr(cp, '/', path + len - cp);
> if (!cp)
> baselen = len;
> else
> baselen = cp - path;
> - strbuf_setlen(&sb, 0);
> + strbuf_reset(&sb);
> strbuf_add(&sb, path, baselen);
> if (!is_directory(sb.buf))
> break;
> - if (simplify_away(sb.buf, sb.len, pathspec))
> - break;
> - if (treat_one_path(dir, NULL, istate, &sb, baselen, pathspec,
> - DT_DIR, NULL) == path_none)
> + strbuf_reset(&sb);
> + strbuf_add(&sb, path, prevlen);
> + memcpy(de.d_name, path+prevlen, baselen-prevlen);But here we try to copy a path into that `de.d_name`, which is still `NULL`?
That can't be right, can it?
Thanks for your help, Dscho
Show 57 quoted lines
> + de.d_name[baselen-prevlen] = '\0';
> + state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
> + pathspec);
> + if (state != path_recurse)
> break; /* do not recurse into it */
> - if (len <= baselen) {
> - rc = 1;
> + if (len <= baselen)
> break; /* finished checking */
> - }
> }
> + add_path_to_appropriate_result_list(dir, NULL, &cdir, istate,
> + &sb, baselen, pathspec,
> + state);
> +
> strbuf_release(&sb);
> - return rc;
> + return state == path_recurse;
> }
>
> static const char *get_ident_string(void)
> diff --git a/t/t3011-common-prefixes-and-directory-traversal.sh b/t/t3011-common-prefixes-and-directory-traversal.sh
> index d6e161ddd8..098fddc75b 100755
> --- a/t/t3011-common-prefixes-and-directory-traversal.sh
> +++ b/t/t3011-common-prefixes-and-directory-traversal.sh
> @@ -74,7 +74,7 @@ test_expect_success 'git ls-files -o --directory untracked_dir does not recurse'
> test_cmp expect actual
> '
>
> -test_expect_failure 'git ls-files -o --directory untracked_dir/ does not recurse' '
> +test_expect_success 'git ls-files -o --directory untracked_dir/ does not recurse' '
> echo untracked_dir/ >expect &&
> git ls-files -o --directory untracked_dir/ >actual &&
> test_cmp expect actual
> @@ -86,7 +86,7 @@ test_expect_success 'git ls-files -o untracked_repo does not recurse' '
> test_cmp expect actual
> '
>
> -test_expect_failure 'git ls-files -o untracked_repo/ does not recurse' '
> +test_expect_success 'git ls-files -o untracked_repo/ does not recurse' '
> echo untracked_repo/ >expect &&
> git ls-files -o untracked_repo/ >actual &&
> test_cmp expect actual
> @@ -133,7 +133,7 @@ test_expect_success 'git ls-files -o .git shows nothing' '
> test_must_be_empty actual
> '
>
> -test_expect_failure 'git ls-files -o .git/ shows nothing' '
> +test_expect_success 'git ls-files -o .git/ shows nothing' '
> git ls-files -o .git/ >actual &&
> test_must_be_empty actual
> '
> --
> gitgitgadget
>
>
>