From: Ted Nyman <[email protected]>
The pathspec parser computes `len` and `nowildcard_len` from
`item.match`, which includes any prefix added when a command is run
from a subdirectory. `item.original` can still contain the shorter,
unprefixed argument.
Using `item.original + item.nowildcard_len` in
`pathspec_needs_expanded_index()` can therefore read past the end of
the allocation. AddressSanitizer reports a heap-buffer-overflow for
prefixed wildcard pathspecs passed to `git rm` and `git reset` with a
sparse index.
The mismatch dates back to 4d1cfc1351 ("reset: make --mixed
sparse-aware", 2021-11-29), which introduced the helper using
`item.original`. b29ad38322 ("pathspec.h: move
pathspec_needs_expanded_index() from reset.c to here", 2022-08-07)
later moved it to `pathspec.c` and preserved the affected comparisons.
Use `item.match` consistently when checking whether a pathspec can
match a sparse-directory entry. Add coverage for prefixed wildcard
pathspecs so both commands keep the index sparse.
Signed-off-by: Ted Nyman <[email protected]>
---
pathspec.c | 12 ++++++------
t/t1092-sparse-checkout-compatibility.sh | 7 +++++++
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/pathspec.c b/pathspec.c
index f78b22709ccb67..281858f21f9c59 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -847,9 +847,9 @@ int pathspec_needs_expanded_index(struct index_state *istate,
* - not-in-cone/bar*: may need expanded index
* - **.c: may need expanded index
*/
- if (strspn(item.original + item.nowildcard_len, "*") ==
+ if (strspn(item.match + item.nowildcard_len, "*") ==
(unsigned int)(item.len - item.nowildcard_len) &&
- path_in_cone_mode_sparse_checkout(item.original, istate))
+ path_in_cone_mode_sparse_checkout(item.match, istate))
continue;
for (pos = 0; pos < istate->cache_nr; pos++) {
@@ -865,7 +865,7 @@ int pathspec_needs_expanded_index(struct index_state *istate,
*/
if ((unsigned int)item.nowildcard_len >
ce_namelen(ce) &&
- !strncmp(item.original, ce->name,
+ !strncmp(item.match, ce->name,
ce_namelen(ce))) {
res = 1;
break;
@@ -876,13 +876,13 @@ int pathspec_needs_expanded_index(struct index_state *istate,
* directory and the pathspec does not match the whole
* directory, need to expand the index.
*/
- if (!strncmp(item.original, ce->name, item.nowildcard_len) &&
- wildmatch(item.original, ce->name, 0)) {
+ if (!strncmp(item.match, ce->name, item.nowildcard_len) &&
+ wildmatch(item.match, ce->name, 0)) {
res = 1;
break;
}
}
- } else if (!path_in_cone_mode_sparse_checkout(item.original, istate) &&
+ } else if (!path_in_cone_mode_sparse_checkout(item.match, istate) &&
!matches_skip_worktree(pathspec, i, &skip_worktree_seen))
res = 1;
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 9814431cd74aff..d0b42371663f9d 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -2119,6 +2119,13 @@ test_expect_success 'sparse index is not expanded: rm' '
ensure_not_expanded rm -r deep
'
+test_expect_success 'sparse index is not expanded: prefixed wildcard pathspec' '
+ init_repos &&
+
+ ensure_not_expanded -C deep rm --dry-run -- "a*" &&
+ ensure_not_expanded -C deep reset base -- "a*"
+'
+
test_expect_success 'grep with and --cached' '
init_repos &&
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.