fsck: use parse_unsigned_from_buf() for parsing timestamp

In 5a993593b2 (fsck: avoid parse_timestamp() on buffer that isn't
NUL-terminated, 2025-11-18), we added a wrapper that copies the
timestamp into a buffer before calling parse_timestamp().

Now that we have a more robust helper for parsing from a buffer, we can
drop our wrapper and switch to that. We could just do so inline, but the
choice of "unsigned" vs "signed" depends on the typedef of timestamp_t.
So we'll wrap that in a macro that is defined alongside the rest of the
timestamp abstraction.

The resulting function is almost a drop-in replacement, but the new
interface means we need to hold the result in a separate timestamp_t,
rather than returning it directly from one function into the parameter
of another. The old one did still detect overflow errors by returning
TIME_MAX, since date_overflows() checks for that, but now we'll see it
more directly from the return of parse_timestamp_from_buf(). The
behavior should be the same.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2025-11-30 08:16:02 -05:00 committed by Junio C Hamano
parent 7cf9c96646
commit 247c6598a8
2 changed files with 5 additions and 17 deletions

View File

@ -253,6 +253,8 @@ char *gitdirname(char *);
typedef uintmax_t timestamp_t;
#define PRItime PRIuMAX
#define parse_timestamp strtoumax
#define parse_timestamp_from_buf(buf, len, ep, result) \
parse_unsigned_from_buf((buf), (len), (ep), (result), TIME_MAX)
#define TIME_MAX UINTMAX_MAX
#define TIME_MIN 0

20
fsck.c
View File

@ -860,28 +860,13 @@ static int verify_headers(const void *data, unsigned long size,
FSCK_MSG_UNTERMINATED_HEADER, "unterminated header");
}
static timestamp_t parse_timestamp_from_buf(const char **start, const char *end)
{
const char *p = *start;
char buf[24]; /* big enough for 2^64 */
size_t i = 0;
while (p < end && isdigit(*p)) {
if (i >= ARRAY_SIZE(buf) - 1)
return TIME_MAX;
buf[i++] = *p++;
}
buf[i] = '\0';
*start = p;
return parse_timestamp(buf, NULL, 10);
}
static int fsck_ident(const char **ident, const char *ident_end,
const struct object_id *oid, enum object_type type,
struct fsck_options *options)
{
const char *p = *ident;
const char *nl;
timestamp_t timestamp;
nl = memchr(p, '\n', ident_end - p);
if (!nl)
@ -933,7 +918,8 @@ static int fsck_ident(const char **ident, const char *ident_end,
"invalid author/committer line - bad date");
if (*p == '0' && p[1] != ' ')
return report(options, oid, type, FSCK_MSG_ZERO_PADDED_DATE, "invalid author/committer line - zero-padded date");
if (date_overflows(parse_timestamp_from_buf(&p, ident_end)))
if (!parse_timestamp_from_buf(p, ident_end - p, &p, &timestamp) ||
date_overflows(timestamp))
return report(options, oid, type, FSCK_MSG_BAD_DATE_OVERFLOW, "invalid author/committer line - date causes integer overflow");
if (*p != ' ')
return report(options, oid, type, FSCK_MSG_BAD_DATE, "invalid author/committer line - bad date");