From: Junio C Hamano <gitster@pobox.com>
To: "Ravi Mistry via GitGitGadget" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org,
Abhijeetsingh Meena <abhijeet040403@gmail.com>,
Kristoffer Haugsbakk <code@khaugsbakk.name>,
Phillip Wood <phillip.wood@dunelm.org.uk>,
Eric Sunshine <sunshine@sunshineco.com>,
Ravi Mistry <rmistry@google.com>
Subject: Re: [PATCH v2 1/2] blame: harden ignore-revs parser and tag peeling
Date: Thu, 08 Oct 2026 22:07:27 -0700 [thread overview]
Message-ID: <xmqqjynrwjg0.fsf@gitster.g> (raw)
In-Reply-To: <2e12486c0d5dd8b94393b08413a85a8d47f86edd.1791493644.git.gitgitgadget@gmail.com> (Ravi Mistry via GitGitGadget's message of "Thu, 08 Oct 2026 21:07:23 +0000")
"Ravi Mistry via GitGitGadget" <gitgitgadget@gmail.com> writes:
> - In oidset_parse_file_carefully(), strbuf_getline() reads up to the
> next newline and records the full line length in sb.len, including
> any embedded NUL bytes. However, strchr(sb.buf, '#') and
> parse_oid_hex_algop(sb.buf, &oid, &p, algop) treat sb.buf as a
> NUL-terminated string. If a line contains an embedded NUL byte after
> a valid object name (such as "<oid>\0garbage" or "<oid>\0# comment"),
> *p is '\0' and trailing bytes on the line are silently ignored.
> Reject any line containing an embedded NUL byte via memchr() before
> stripping comments and whitespace.
Maybe I am slow, but I do not immediately see why ignoring
everything after the first NUL is a problem. A call to
strbuf_trim() is ineffective at trimming whitespace that appears
immediately before such a NUL. For example, while
cf9bdb1...f6092d # comment LF
would feed the leading 'cf9bdb1...f6092d' part (after stripping
whitespace before '#') to parse_oid_hex_algop(), this
cf9bdb1...f6092d NUL comment LF
would keep the whitespace after '92d' and cause the parsing to
fail. I do not see any security implications here.
On the other hand ...
> - In peel_to_commit_oid(), odb_read_object_info() is called without
> OBJECT_INFO_SKIP_FETCH_OBJECT or OBJECT_INFO_QUICK, and deref_tag()
> calls parse_object() on tag targets without checking whether the
> target object exists locally first. In a partial clone, any missing
> commit OID or tag target listed in the ignore-revs file would trigger
> lazy promisor fetches and pack directory rescans during git-blame(1).
> Use odb_read_object_info_extended() with OBJECT_INFO_LOOKUP_REPLACE |
> OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK and peel OBJ_TAG
> objects one layer per iteration, verifying that each target object
> exists locally and matches the tag's declared type before parsing it.
... this may be a very reasonable thing to do, I would think. In a
shallow clone, if we are not auto-deepening the shallow boundary
during a "git blame" session, we have no reason to lazy fetch
entries in the ignore file that are older than the shallow boundary.
> diff --git a/oidset.c b/oidset.c
> index c8ff0b385c..90d39204d3 100644
> --- a/oidset.c
> +++ b/oidset.c
> @@ -85,6 +85,9 @@ void oidset_parse_file_carefully(struct oidset *set, const char *path,
> const char *p;
> const char *name;
>
> + if (memchr(sb.buf, '\0', sb.len))
> + die("invalid object name: %s", sb.buf);
A file with such an entry is rejected and the entire operation is
aborted as suspected attack attempt, which feels like striking the
balance between usability and security at a wrong place.
But a line with broken object name already is rejected with "die()"
with the existing code, so it may be OK.
> diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh
> index cace00ae8d..70fe509a64 100755
> --- a/t/t8013-blame-ignore-revs.sh
> +++ b/t/t8013-blame-ignore-revs.sh
> @@ -327,4 +327,42 @@ test_expect_success ignore_merge '
> test_cmp expect actual
> '
>
> +test_expect_success 'ignore-revs-file rejects lines with embedded NUL bytes' '
> + rev_b=$(git rev-parse B) &&
> + printf "%sQgarbage\n" "$rev_b" | q_to_nul >ignore_nul &&
> + test_must_fail git blame file --ignore-revs-file ignore_nul 2>err &&
> + test_grep "invalid object name:" err &&
> +
> + printf "%sQ# comment\n" "$rev_b" | q_to_nul >ignore_nul_comment &&
> + test_must_fail git blame file --ignore-revs-file ignore_nul_comment 2>err &&
> + test_grep "invalid object name:" err
> +'
> +
> +test_expect_success 'ignore-revs-file peels chained tags and skips missing tag targets' '
> + test_write_lines BB L2-modified L3 L4 L5 L6 L7 L8 CC >file &&
> + git add file &&
> + test_tick &&
> + git commit -m D &&
> + git tag -a -m "tag 1" D_TAG1 HEAD &&
> + git tag -a -m "tag 2" D_TAG2 D_TAG1 &&
> + git rev-parse D_TAG2 >ignore_tag_chain &&
> + git blame --line-porcelain file --ignore-revs-file ignore_tag_chain >blame_raw &&
> + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual &&
> + git rev-parse A >expect &&
> + test_cmp expect actual &&
> +
> + test_config extensions.partialClone origin &&
> + test_config remote.origin.promisor true &&
> + test_config remote.origin.url /nonexistent &&
> + missing_oid=$(test_oid deadbeef) &&
> + bad_tag=$(printf "object %s\ntype commit\ntag bad-tag\ntagger T <t@example.com> 0 +0000\n\nmsg\n" "$missing_oid" |
> + git hash-object -t tag -w --stdin) &&
> + test_write_lines "$missing_oid" "$bad_tag" >ignore_bad_tag &&
> + git blame --line-porcelain file --ignore-revs-file ignore_bad_tag >blame_raw 2>err &&
> + test_must_be_empty err &&
> + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual &&
> + git rev-parse HEAD >expect &&
> + test_cmp expect actual
> +'
> +
> test_done
next prev parent reply other threads:[~2026-10-09 5:07 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 23:29 [PATCH] blame: default to ignoring revisions in .git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-09-30 14:59 ` Ravi Mistry
2026-10-05 15:37 ` Junio C Hamano
2026-10-05 21:12 ` Ravi Mistry
2026-10-07 17:43 ` Junio C Hamano
2026-10-07 18:07 ` Ravi Mistry
2026-10-08 21:07 ` [PATCH v2 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-08 21:07 ` [PATCH v2 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-09 5:07 ` Junio C Hamano [this message]
2026-10-10 19:25 ` Ravi Mistry
2026-10-08 21:07 ` [PATCH v2 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-09 20:17 ` Junio C Hamano
2026-10-10 6:12 ` Eric Sunshine
2026-10-10 18:40 ` Ravi Mistry
2026-10-11 18:58 ` Junio C Hamano
2026-10-11 22:29 ` Ravi Mistry
2026-10-11 23:07 ` Junio C Hamano
2026-10-12 9:13 ` Phillip Wood
2026-10-12 16:38 ` Junio C Hamano
2026-10-12 19:21 ` Ravi Mistry
2026-10-12 21:13 ` Junio C Hamano
2026-10-13 14:48 ` Ravi Mistry
2026-10-11 22:21 ` [PATCH v3 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-11 22:21 ` [PATCH v3 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-11 22:21 ` [PATCH v3 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-12 9:10 ` Phillip Wood
2026-10-12 15:48 ` Ravi Mistry
2026-10-12 19:17 ` [PATCH v4 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-12 19:17 ` [PATCH v4 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-12 19:17 ` [PATCH v4 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 0/2] blame: ignore revs in .git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 2/2] blame: ignore revs in .git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqqjynrwjg0.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=abhijeet040403@gmail.com \
--cc=code@khaugsbakk.name \
--cc=git@vger.kernel.org \
--cc=gitgitgadget@gmail.com \
--cc=phillip.wood@dunelm.org.uk \
--cc=rmistry@google.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.