From: "darcy via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: darcy <acednes@gmail.com>, darcy <acednes@gmail.com>
Subject: [PATCH v3] date: detect underflow/overflow when parsing dates with timezone offset
Date: Fri, 07 Jun 2024 00:17:08 +0000 [thread overview]
Message-ID: <pull.1726.v3.git.git.1717719428510.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1726.v2.git.git.1717369608923.gitgitgadget@gmail.com>
From: darcy <acednes@gmail.com>
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
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".
Signed-off-by: Darcy Burke <acednes@gmail.com>
---
fix: prevent date underflow when using positive timezone offset
cc: Patrick Steinhardt ps@pks.im cc: Phillip Wood
phillip.wood123@gmail.com cc: darcy acednes@gmail.com cc: Jeff King
peff@peff.net
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1726%2Fdxrcy%2Fmaster-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1726/dxrcy/master-v3
Pull-Request: https://github.com/git/git/pull/1726
Range-diff vs v2:
1: db508b2f533 ! 1: f0de3a2c543 date: detect underflow when parsing dates with positive timezone offset
@@ Metadata
Author: darcy <acednes@gmail.com>
## Commit message ##
- date: detect underflow when parsing dates with positive timezone offset
+ date: detect underflow/overflow when parsing dates with timezone offset
Overriding the date of a commit to be close to "1970-01-01 00:00:00"
- with a large enough timezone for the equivelant GMT time to be before
- the epoch is considered valid by `parse_date_basic`.
+ 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 in the commit timestamp, which is not
- caught by `git-commit`, but will cause other services to fail, such as
- `git-fsck`, which reports "badDateOverflow: invalid author/committer
- line - date causes integer overflow".
+ This leads to an integer underflow or underflow respectively in the
+ 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", when parsing.
+ before the epoch "1970-01-01T00:00:00Z" or after the maximum date
+ "2099-12-31T23:59:59Z".
Signed-off-by: Darcy Burke <acednes@gmail.com>
## date.c ##
+@@ date.c: static int match_object_header_date(const char *date, timestamp_t *timestamp, in
+ return 0;
+ }
+
++
++/* 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;
++
+ /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
+ (i.e. English) day/month names, and it doesn't work correctly with %z. */
+ int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
@@ date.c: int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
}
}
@@ date.c: int parse_date_basic(const char *date, timestamp_t *timestamp, int *offs
- 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;
+ }
@@ date.c: int parse_date_basic(const char *date, timestamp_t *timestamp, int *offs
## t/t0006-date.sh ##
-@@ t/t0006-date.sh: check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
- check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
+@@ t/t0006-date.sh: check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
+
+check_parse '1970-01-01 00:00:00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 +00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 Z' '1970-01-01 00:00:00 +0000'
@@ t/t0006-date.sh: check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +00
+check_parse '1969-12-31 23:59:59 Z' bad
+check_parse '1969-12-31 23:59:59 +11' bad
+check_parse '1969-12-31 23:59:59 -11' bad
-
++
++check_parse '2099-12-31 23:59:59' '2099-12-31 23:59:59 +0000'
++check_parse '2099-12-31 23:59:59 +00' '2099-12-31 23:59:59 +0000'
++check_parse '2099-12-31 23:59:59 Z' '2099-12-31 23:59:59 +0000'
++check_parse '2099-12-31 23:59:59 +01' '2099-12-31 23:59:59 +0100'
++check_parse '2099-12-31 23:59:59 -01' bad
++check_parse '2099-12-31 23:59:59 -11' bad
++check_parse '2099-12-31 23:00:00 -01' bad
++check_parse '2099-12-31 22:59:59 -01' '2099-12-31 22:59:59 -0100'
++check_parse '2100-00-00 00:00:00' bad
++check_parse '2099-12-30 00:00:00 -11' '2099-12-30 00:00:00 -1100'
++check_parse '2100-00-00 00:00:00 +00' bad
++check_parse '2100-00-00 00:00:00 Z' bad
++check_parse '2100-00-00 00:00:00 -11' bad
++check_parse '2100-00-00 00:00:00 +11' bad
++
check_approxidate() {
echo "$1 -> $2 +0000" >expect
+ test_expect_${3:-success} "parse approxidate ($1)" "
date.c | 12 +++++++++++-
t/t0006-date.sh | 31 +++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/date.c b/date.c
index 7365a4ad24f..95776c8a92f 100644
--- a/date.c
+++ b/date.c
@@ -868,6 +868,10 @@ static int match_object_header_date(const char *date, timestamp_t *timestamp, in
return 0;
}
+
+/* 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;
+
/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
(i.e. English) day/month names, and it doesn't work correctly with %z. */
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 */
}
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 3031256d143..e8fdf361ad4 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -117,6 +117,37 @@ check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
+check_parse '1970-01-01 00:00:00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 +00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 Z' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 -01' '1970-01-01 00:00:00 -0100'
+check_parse '1970-01-01 00:00:00 +01' bad
+check_parse '1970-01-01 00:00:00 +11' bad
+check_parse '1970-01-01 00:59:59 +01' bad
+check_parse '1970-01-01 01:00:00 +01' '1970-01-01 01:00:00 +0100'
+check_parse '1970-01-01 01:00:00 +11' bad
+check_parse '1970-01-02 00:00:00 +11' '1970-01-02 00:00:00 +1100'
+check_parse '1969-12-31 23:59:59' bad
+check_parse '1969-12-31 23:59:59 +00' bad
+check_parse '1969-12-31 23:59:59 Z' bad
+check_parse '1969-12-31 23:59:59 +11' bad
+check_parse '1969-12-31 23:59:59 -11' bad
+
+check_parse '2099-12-31 23:59:59' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +00' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 Z' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +01' '2099-12-31 23:59:59 +0100'
+check_parse '2099-12-31 23:59:59 -01' bad
+check_parse '2099-12-31 23:59:59 -11' bad
+check_parse '2099-12-31 23:00:00 -01' bad
+check_parse '2099-12-31 22:59:59 -01' '2099-12-31 22:59:59 -0100'
+check_parse '2100-00-00 00:00:00' bad
+check_parse '2099-12-30 00:00:00 -11' '2099-12-30 00:00:00 -1100'
+check_parse '2100-00-00 00:00:00 +00' bad
+check_parse '2100-00-00 00:00:00 Z' bad
+check_parse '2100-00-00 00:00:00 -11' bad
+check_parse '2100-00-00 00:00:00 +11' bad
+
check_approxidate() {
echo "$1 -> $2 +0000" >expect
test_expect_${3:-success} "parse approxidate ($1)" "
base-commit: cd77e87115eab5e80e6b161e7b84a79ba1a12cdc
--
gitgitgadget
next prev parent reply other threads:[~2024-06-07 0:17 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-27 9:17 [PATCH] fix: prevent date underflow when using positive timezone offset darcy via GitGitGadget
2024-05-28 14:05 ` Patrick Steinhardt
2024-05-28 14:49 ` Phillip Wood
2024-05-28 17:06 ` Junio C Hamano
2024-06-02 23:06 ` [PATCH v2] date: detect underflow when parsing dates with " darcy via GitGitGadget
2024-06-03 11:13 ` Junio C Hamano
2024-06-03 11:44 ` darcy
2024-06-03 14:13 ` Phillip Wood
2024-06-04 8:48 ` darcy
2024-06-04 9:33 ` Jeff King
2024-06-05 6:52 ` darcy
2024-06-05 13:10 ` Phillip Wood
2024-06-05 17:27 ` Junio C Hamano
2024-06-06 4:56 ` darcy
2024-06-07 0:17 ` darcy via GitGitGadget [this message]
2024-06-07 17:40 ` [PATCH v3] date: detect underflow/overflow when parsing dates with " Junio C Hamano
2024-06-08 18:58 ` Junio C Hamano
2024-06-14 1:20 ` Junio C Hamano
2024-06-15 11:47 ` Karthik Nayak
2024-06-11 23:30 ` Junio C Hamano
2024-06-11 23:49 ` rsbecker
2024-06-11 23:52 ` Junio C Hamano
2024-06-25 23:12 ` [PATCH v4 0/2] Darcy's "date underflow fix" topic, final reroll Junio C Hamano
2024-06-25 23:12 ` [PATCH v4 1/2] t0006: simplify prerequisites Junio C Hamano
2024-06-25 23:30 ` Eric Sunshine
2024-06-26 0:04 ` Junio C Hamano
2024-06-25 23:12 ` [PATCH v4 2/2] date: detect underflow/overflow when parsing dates with timezone offset Junio C Hamano
2024-06-26 15:21 ` [PATCH v4 0/2] Darcy's "date underflow fix" topic, final reroll Phillip Wood
2024-06-26 18:32 ` Junio C Hamano
2024-06-12 9:07 ` [PATCH v3] date: detect underflow/overflow when parsing dates with timezone offset Phillip Wood
2024-06-12 9:49 ` Karthik Nayak
2024-06-13 13:31 ` Phillip Wood
2024-06-13 16:16 ` Junio C Hamano
2024-06-14 20:09 ` Karthik Nayak
2024-06-14 21:02 ` Junio C Hamano
2024-06-15 11:49 ` Karthik Nayak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1726.v3.git.git.1717719428510.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=acednes@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.