[PATCH 4/4] fsck: use parse_unsigned_from_buf() for parsing timestamp
From: Jeff King <hidden>
Date: 2025-11-30 13:16:04
Subsystem:
the rest · Maintainer:
Linus Torvalds
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 <redacted> --- compat/posix.h | 2 ++ fsck.c | 20 +++----------------- 2 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
index 067a00f33b..d2dbc3e2a5 100644
--- a/compat/posix.h
+++ b/compat/posix.h@@ -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
diff --git a/fsck.c b/fsck.c
index 8e8083e7c6..68a23ae628 100644
--- a/fsck.c
+++ b/fsck.c@@ -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, ×tamp) || + 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");
--
2.52.0.413.gf695cdb9bd