{"thread":{"id":"66253","subject":"[PATCH] dir: do not apply prefix to negative pathspecs","startedAt":"2026-09-02T12:22:54Z","lastAt":"2026-09-03T10:07:32Z","messageCount":2,"participants":["Yannik Tausch"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"551749","messageId":"0CA8678D-0540-4A2E-B314-B9BEB04E2BF5@ytausch.de","threadId":"66253","inReplyTo":null,"subject":"[PATCH] dir: do not apply prefix to negative pathspecs","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-09-02T12:22:39Z","receivedAt":"2026-09-02T12:22:54Z","isPatch":true,"body":"common_prefix_len() derives the common prefix solely from positive\npathspecs, skipping those marked with PATHSPEC_EXCLUDE. However,\nmatch_pathspec_with_flags() also passes that prefix when matching the\nnegative pathspecs.\n\nA negative pathspec may be shorter than the prefix. In that case,\nmatch_pathspec_item() advances item->match beyond its allocation and\nsubtracts the prefix from item->len, producing a negative matchlen. It\nthen dereferences the out-of-bounds pointer. If the resulting byte is\nnot NUL, matchlen is converted to size_t when passed to ps_strncmp(),\nwhich may cause a much larger out-of-bounds read.\n\nThe problem can be reproduced with AddressSanitizer:\n\n    make SANITIZE=address CFLAGS=\"-g -O0\" git\n    git init test &&\n    cd test &&\n    DIR=$(printf \"a%.0s\" {1..150}) &&\n    mkdir -p \"$DIR\" &&\n    touch \"$DIR/f.txt\" &&\n    git add -A &&\n    git commit -m test &&\n    ../git ls-files -- \"$DIR/\" \":(exclude)xy\"\n\nThis reports a heap-buffer-overflow. Without AddressSanitizer, the\noutput may depend on the contents of memory following the negative\npathspec.\n\nFix the bug by using a zero prefix when matching negative pathspecs.\nAdd a regression test that combines a positive pathspec with a longer\ncommon prefix and a shorter, unrelated negative pathspec.\n\nSigned-off-by: Yannik Tausch <dev@ytausch.de>\n---\n\nNote that I already sent information about this issue to the git security\nmailing list on July 31, where I was informed that a fix of this kind does\nnot require an embargo.\n\n dir.c                       | 2 +-\n t/t6132-pathspec-exclude.sh | 9 +++++++++\n 2 files changed, 10 insertions(+), 1 deletion(-)\n\ndiff --git a/dir.c b/dir.c\nindex 95d8a1cce9..7072715389 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -593,7 +593,7 @@ static int match_pathspec_with_flags(struct index_state *istate,\n \tif (!(ps->magic & PATHSPEC_EXCLUDE) || !positive)\n \t\treturn positive;\n \tnegative = do_match_pathspec(istate, ps, name, namelen,\n-\t\t\t\t     prefix, seen,\n+\t\t\t\t     0, seen,\n \t\t\t\t     flags | DO_MATCH_EXCLUDE);\n \treturn negative ? 0 : positive;\n }\ndiff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh\nindex 9fdafeb1e9..ad919cc739 100755\n--- a/t/t6132-pathspec-exclude.sh\n+++ b/t/t6132-pathspec-exclude.sh\n@@ -183,6 +183,15 @@ EOF\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'negative pathspec shorter than positive pathspec prefix' '\n+\tgit ls-files -- sub/sub/ \":(exclude)sub2\" >actual &&\n+\tcat <<-\\EOF >expect &&\n+\tsub/sub/file\n+\tsub/sub/sub/file\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'multiple exclusions' '\n \tgit ls-files -- \":^*/file2\" \":^sub2\" >actual &&\n \tcat <<-\\EOF >expect &&\n\n"},{"id":"551854","messageId":"41A4C5A6-17FF-4048-9C18-BA78C8DBAA49@ytausch.de","threadId":"66253","inReplyTo":"0CA8678D-0540-4A2E-B314-B9BEB04E2BF5@ytausch.de","subject":"Re: [PATCH] dir: do not apply prefix to negative pathspecs","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-09-03T10:07:16Z","receivedAt":"2026-09-03T10:07:32Z","isPatch":true,"body":"Note that v2 is here: https://lore.kernel.org/git/81EC0E28-13E7-4D10-BD07-3601124CBD77@ytausch.de/T/#md8de0b0b0e4426847abd60890e6db05da010b204"}]}