unmarshal: validate date (#622)

This commit is contained in:
Johanan Idicula
2021-10-17 20:18:20 -04:00
committed by GitHub
parent 85f5d567e4
commit 76f53c857b
3 changed files with 65 additions and 1 deletions
+39
View File
@@ -43,6 +43,10 @@ func parseLocalDate(b []byte) (LocalDate, error) {
date.Day = parseDecimalDigits(b[8:10])
if !isValidDate(date.Year, date.Month, date.Day) {
return LocalDate{}, newDecodeError(b, "impossible date")
}
return date, nil
}
@@ -330,3 +334,38 @@ func checkAndRemoveUnderscores(b []byte) ([]byte, error) {
return cleaned, nil
}
// isValidDate checks if a provided date is a date that exists.
func isValidDate(year int, month int, day int) bool {
return day <= daysIn(month, year)
}
// daysBefore[m] counts the number of days in a non-leap year
// before month m begins. There is an entry for m=12, counting
// the number of days before January of next year (365).
var daysBefore = [...]int32{
0,
31,
31 + 28,
31 + 28 + 31,
31 + 28 + 31 + 30,
31 + 28 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
}
func daysIn(m int, year int) int {
if m == 2 && isLeap(year) {
return 29
}
return int(daysBefore[m] - daysBefore[m-1])
}
func isLeap(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
-1
View File
@@ -176,7 +176,6 @@ func TestTOMLTest_Invalid_Control_StringUs(t *testing.T) {
}
func TestTOMLTest_Invalid_Datetime_ImpossibleDate(t *testing.T) {
t.Skip("FIXME")
input := "d = 2006-01-50T00:00:00Z\n"
testgenInvalid(t, input)
}
+26
View File
@@ -353,6 +353,22 @@ func TestUnmarshal(t *testing.T) {
}
},
},
{
desc: "local leap-day date into interface",
input: `a = 2020-02-29`,
gen: func() test {
type doc struct {
A interface{}
}
return test{
target: &doc{},
expected: &doc{
A: toml.LocalDate{2020, 2, 29},
},
}
},
},
{
desc: "local-time with nano second",
input: `a = 12:08:05.666666666`,
@@ -2091,6 +2107,16 @@ world'`,
desc: "multiline basic string with unfinished escape sequence after the first escape code",
data: "a = \"\"\"\\t\\",
},
{
desc: `impossible date-day`,
data: `A = 2021-03-40T23:59:00`,
msg: `impossible date`,
},
{
desc: `leap day in non-leap year`,
data: `A = 2021-02-29T23:59:00`,
msg: `impossible date`,
},
}
for _, e := range examples {