aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Pan <panjf2000@gmail.com>2021-03-12 19:40:46 +0800
committerIan Lance Taylor <iant@golang.org>2021-03-17 19:48:52 +0000
commita5df88355cb8998856a5dbd3550b98e5de1f6009 (patch)
tree754da0398f9f9ed80f77092965dd446c8bb8a79a
parent5423f6023cff995f1077ac83e132705893a8af79 (diff)
downloadgo-a5df88355cb8998856a5dbd3550b98e5de1f6009.tar.gz
go-a5df88355cb8998856a5dbd3550b98e5de1f6009.zip
time: check int64 overflow in Time.addSec
Change-Id: Ibbed54239228e7ea31ef5978d427425899c3b943 Reviewed-on: https://go-review.googlesource.com/c/go/+/300890 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Trust: Baokun Lee <bk@golangcn.org>
-rw-r--r--src/time/export_test.go1
-rw-r--r--src/time/internal_test.go2
-rw-r--r--src/time/time.go11
-rw-r--r--src/time/time_test.go27
4 files changed, 38 insertions, 3 deletions
diff --git a/src/time/export_test.go b/src/time/export_test.go
index f4a8cd9b72..0f2d21053a 100644
--- a/src/time/export_test.go
+++ b/src/time/export_test.go
@@ -51,6 +51,7 @@ const (
RuleJulian = RuleKind(ruleJulian)
RuleDOY = RuleKind(ruleDOY)
RuleMonthWeekDay = RuleKind(ruleMonthWeekDay)
+ UnixToInternal = unixToInternal
)
type Rule struct {
diff --git a/src/time/internal_test.go b/src/time/internal_test.go
index ffe54e47c2..87a4208b05 100644
--- a/src/time/internal_test.go
+++ b/src/time/internal_test.go
@@ -62,4 +62,6 @@ func CheckRuntimeTimerPeriodOverflow() {
var (
MinMonoTime = Time{wall: 1 << 63, ext: -1 << 63, loc: UTC}
MaxMonoTime = Time{wall: 1 << 63, ext: 1<<63 - 1, loc: UTC}
+
+ NotMonoNegativeTime = Time{wall: 0, ext: -1<<63 + 50}
)
diff --git a/src/time/time.go b/src/time/time.go
index 7e5192a0c9..841f989293 100644
--- a/src/time/time.go
+++ b/src/time/time.go
@@ -189,8 +189,15 @@ func (t *Time) addSec(d int64) {
t.stripMono()
}
- // TODO: Check for overflow.
- t.ext += d
+ // Check if the sum of t.ext and d overflows and handle it properly.
+ sum := t.ext + d
+ if (sum > t.ext) == (d > 0) {
+ t.ext = sum
+ } else if d > 0 {
+ t.ext = 1<<63 - 1
+ } else {
+ t.ext = -(1<<63 - 1)
+ }
}
// setLoc sets the location associated with the time.
diff --git a/src/time/time_test.go b/src/time/time_test.go
index 8884731e1d..3a58bfe4e9 100644
--- a/src/time/time_test.go
+++ b/src/time/time_test.go
@@ -1481,7 +1481,7 @@ func TestTimeIsDST(t *testing.T) {
tzFixed := FixedZone("FIXED_TIME", 12345)
tests := [...]struct {
- time Time
+ time Time
want bool
}{
0: {Date(2009, 1, 1, 12, 0, 0, 0, UTC), false},
@@ -1501,3 +1501,28 @@ func TestTimeIsDST(t *testing.T) {
}
}
}
+
+func TestTimeAddSecOverflow(t *testing.T) {
+ // Test it with positive delta.
+ var maxInt64 int64 = 1<<63 - 1
+ timeExt := maxInt64 - UnixToInternal - 50
+ notMonoTime := Unix(timeExt, 0)
+ for i := int64(0); i < 100; i++ {
+ sec := notMonoTime.Unix()
+ notMonoTime = notMonoTime.Add(Duration(i * 1e9))
+ if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 {
+ t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64)
+ }
+ }
+
+ // Test it with negative delta.
+ maxInt64 = -maxInt64
+ notMonoTime = NotMonoNegativeTime
+ for i := int64(0); i > -100; i-- {
+ sec := notMonoTime.Unix()
+ notMonoTime = notMonoTime.Add(Duration(i * 1e9))
+ if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 {
+ t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64)
+ }
+ }
+}