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");