From 99cd40b175cc0cd55eb7af5dd4aeffd782f28195 Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Sun, 4 Jan 2026 13:40:19 -0500 Subject: [PATCH] Reject leap seconds to prevent year overflow (#1019) Go's time.Date() normalizes leap seconds (second=60) by adding 1 minute. When parsing the maximum valid TOML date 9999-12-31 23:59:60z, this causes the year to overflow to 10000, which exceeds the valid TOML year range (0000-9999) and breaks round-trip serialization. The fix rejects leap seconds (second > 59) during parsing. This is consistent with the resolution of issue #913 which determined that emitting an error is less surprising than silently normalizing leap seconds. Fixes #1015 Co-authored-by: Claude --- decode.go | 4 ++-- localtime.go | 2 +- unmarshaler_test.go | 12 +++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/decode.go b/decode.go index 4092068..f3f14ef 100644 --- a/decode.go +++ b/decode.go @@ -230,8 +230,8 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) { return t, nil, err } - if t.Second > 60 { - return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60") + if t.Second > 59 { + return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater than 59") } b = b[8:] diff --git a/localtime.go b/localtime.go index a856bfd..502ef2f 100644 --- a/localtime.go +++ b/localtime.go @@ -45,7 +45,7 @@ func (d *LocalDate) UnmarshalText(b []byte) error { type LocalTime struct { Hour int // Hour of the day: [0; 24[ Minute int // Minute of the hour: [0; 60[ - Second int // Second of the minute: [0; 60[ + Second int // Second of the minute: [0; 59] Nanosecond int // Nanoseconds within the second: [0, 1000000000[ Precision int // Number of digits to display for Nanosecond. } diff --git a/unmarshaler_test.go b/unmarshaler_test.go index cdaf509..63fc227 100644 --- a/unmarshaler_test.go +++ b/unmarshaler_test.go @@ -3160,7 +3160,17 @@ world'`, { desc: "invalid seconds value", data: `a=1979-05-27T12:45:99`, - msg: `seconds cannot be greater 60`, + msg: `seconds cannot be greater than 59`, + }, + { + desc: "leap second not supported", + data: `a=1979-05-27T12:45:60`, + msg: `seconds cannot be greater than 59`, + }, + { + desc: "leap second with max date causes overflow", + data: `s=9999-12-31 23:59:60z`, + msg: `seconds cannot be greater than 59`, }, { desc: `binary with invalid digit`,