Re: [PATCH v3] date: detect underflow/overflow when parsing dates with timezone offset
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Jun 7, 2024, 17:40 UTC
- Message-ID
- <xmqq1q58ejnw.fsf@gitster.g>
- In-Reply-To
- <pull.1726.v3.git.git.1717719428510.gitgitgadget@gmail.com>
"darcy via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: darcy <acednes@gmail.com>
This ident should match what is used on "Signed-off-by:" line.
Show 8 quoted lines
> Overriding the date of a commit to be close to "1970-01-01 00:00:00" > with a large enough positive timezone for the equivelant GMT time to be > before the epoch is considered valid by `parse_date_basic`. Similar > behaviour occurs when using a date close to "2099-12-31 23:59:59" (the > maximum date allowed by `tm_to_time_t`) with a large enough negative > timezone offset. > > This leads to an integer underflow or underflow respectively in the
"underflow or underflow respectively"?
Show 8 quoted lines
> commit timestamp, which is not caught by `git-commit`, but will cause > other services to fail, such as `git-fsck`, which, for the first case, > reports "badDateOverflow: invalid author/committer line - date causes > integer overflow". > > Instead check the timezone offset and fail if the resulting time comes > before the epoch "1970-01-01T00:00:00Z" or after the maximum date > "2099-12-31T23:59:59Z".
Nicely described otherwise.
> + > +/* timestamp of 2099-12-31T23:59:59Z, including 32 leap days */ > +static const time_t timestamp_max = ((2100L - 1970) * 365 + 32) * 24 * 60 * 60 - 1;
I wonder if this should be of timestamp_t type instead, as the check is done against *timestamp in parse_date_basic() where *timestamp is of type timestamp_t to match?
Show 16 quoted lines
> int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
> @@ -937,8 +941,14 @@ int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
> }
> }
>
> - if (!tm_gmt)
> + if (!tm_gmt) {
> + if (*offset > 0 && *offset * 60 > *timestamp)
> + return -1;
> + if (*offset < 0 && -*offset * 60 > timestamp_max - *timestamp)
> + return -1;
> *timestamp -= *offset * 60;
> + }
> +
> return 0; /* success */
> }Thanks.