Re: [PATCH 3/3] parse_commit(): handle broken whitespace-only timestamp
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Apr 24, 2023, 18:01 UTC
- Message-ID
- <xmqqy1mhdurt.fsf@gitster.g>
- In-Reply-To
- <20230422135001.GA3942563@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
Show 6 quoted lines
> The comment in parse_commit_date() claims that parse_timestamp() will > not walk past the end of the buffer we've been given, since it will hit > the newline at "eol" and stop. This is usually true, when dateptr > contains actual numbers to parse. But with a line like: > > committer name <email> \n
I was wondering of this case while reading [2/3] ;-)
Show 9 quoted lines
> ... > In practice this can't cause us to walk off the end of an array, because > we always add an extra NUL byte to the end of objects we load from disk > (as a defense against exactly this kind of bug). However, you can see > the behavior in action when "committer" is the final header (which it > usually is, unless there's an encoding) and the subject line can be > parsed as an integer. We walk right past the newline on the committer > line, as well as the "\n\n" separator, and mistake the subject for the > timestamp.
Show 5 quoted lines
> + /* > + * trim leading whitespace; parse_timestamp() will do this itself, but > + * it will walk past the newline at eol while doing so. So we insist > + * that there is at least one digit here. > + */
"one digit" -> "one non-whitespace".
> + while (dateptr < eol && isspace(*dateptr)) > + dateptr++;
This is an expected change, but
> + if (!strchr("0123456789", *dateptr))
> + return 0;this is not. Isn't the only problematic case that dateptr being at eol? That is what the proposed log message argued.
> /* dateptr < eol && *eol == '\n', so parsing will stop at eol */
This comment is slightly stale. dateptr < eol, *eol == '\n', and we know the string starting at dateptr is not a run of whitespace and that is what makes the parsing stop at eol.
Show 12 quoted lines
> diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh > index af4b35ff56..d4ef48d646 100755 > --- a/t/t4212-log-corrupt.sh > +++ b/t/t4212-log-corrupt.sh > @@ -92,4 +92,33 @@ test_expect_success 'absurdly far-in-future date' ' > git log -1 --format=%ad $commit > ' > > +test_expect_success 'create commit with whitespace committer date' ' > + # It is important that this subject line is numeric, since we want to > + # be sure we are not confused by skipping whitespace and accidentally > + # parsing the subject as a timestamp.
Nice.
Show 25 quoted lines
> + # Do not use munge_author_date here. Besides not hitting the committer > + # line, it leaves the timezone intact, and we want nothing but > + # whitespace. > + test_commit 1234567890 && > + git cat-file commit HEAD >commit.orig && > + sed "s/>.*/> /" <commit.orig >commit.munge && > + ws_commit=$(git hash-object --literally -w -t commit commit.munge) > +' > + > +test_expect_success '--until treats whitespace date as sentinel' ' > + echo $ws_commit >expect && > + git rev-list --until=1980-01-01 $ws_commit >actual && > + test_cmp expect actual > +' > + > +test_expect_success 'pretty-printer handles whitespace date' ' > + # as with the %ad test above, we will show these as the empty string, > + # not the 1970 epoch date. This is intentional; see 7d9a281941 (t4212: > + # test bogus timestamps with git-log, 2014-02-24) for more discussion. > + echo : >expect && > + git log -1 --format="%at:%ct" $ws_commit >actual && > + test_cmp expect actual > +' > + > test_done