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 <noreply@anthropic.com>
This commit is contained in:
Thomas Pelletier
2026-01-04 13:40:19 -05:00
committed by GitHub
parent 3aaf147e3e
commit 99cd40b175
3 changed files with 14 additions and 4 deletions
+2 -2
View File
@@ -230,8 +230,8 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
return t, nil, err return t, nil, err
} }
if t.Second > 60 { if t.Second > 59 {
return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60") return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater than 59")
} }
b = b[8:] b = b[8:]
+1 -1
View File
@@ -45,7 +45,7 @@ func (d *LocalDate) UnmarshalText(b []byte) error {
type LocalTime struct { type LocalTime struct {
Hour int // Hour of the day: [0; 24[ Hour int // Hour of the day: [0; 24[
Minute int // Minute of the hour: [0; 60[ 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[ Nanosecond int // Nanoseconds within the second: [0, 1000000000[
Precision int // Number of digits to display for Nanosecond. Precision int // Number of digits to display for Nanosecond.
} }
+11 -1
View File
@@ -3160,7 +3160,17 @@ world'`,
{ {
desc: "invalid seconds value", desc: "invalid seconds value",
data: `a=1979-05-27T12:45:99`, 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`, desc: `binary with invalid digit`,