Decode: add missing checks for LocalTime (#650)
This commit is contained in:
@@ -35,13 +35,22 @@ func parseLocalDate(b []byte) (LocalDate, error) {
|
|||||||
return date, newDecodeError(b, "dates are expected to have the format YYYY-MM-DD")
|
return date, newDecodeError(b, "dates are expected to have the format YYYY-MM-DD")
|
||||||
}
|
}
|
||||||
|
|
||||||
date.Year = parseDecimalDigits(b[0:4])
|
var err error
|
||||||
|
|
||||||
v := parseDecimalDigits(b[5:7])
|
date.Year, err = parseDecimalDigits(b[0:4])
|
||||||
|
if err != nil {
|
||||||
|
return LocalDate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
date.Month = v
|
date.Month, err = parseDecimalDigits(b[5:7])
|
||||||
|
if err != nil {
|
||||||
|
return LocalDate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
date.Day = parseDecimalDigits(b[8:10])
|
date.Day, err = parseDecimalDigits(b[8:10])
|
||||||
|
if err != nil {
|
||||||
|
return LocalDate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
if !isValidDate(date.Year, date.Month, date.Day) {
|
if !isValidDate(date.Year, date.Month, date.Day) {
|
||||||
return LocalDate{}, newDecodeError(b, "impossible date")
|
return LocalDate{}, newDecodeError(b, "impossible date")
|
||||||
@@ -50,15 +59,18 @@ func parseLocalDate(b []byte) (LocalDate, error) {
|
|||||||
return date, nil
|
return date, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDecimalDigits(b []byte) int {
|
func parseDecimalDigits(b []byte) (int, error) {
|
||||||
v := 0
|
v := 0
|
||||||
|
|
||||||
for _, c := range b {
|
for i, c := range b {
|
||||||
|
if c < '0' || c > '9' {
|
||||||
|
return 0, newDecodeError(b[i:i+1], "expected digit (0-9)")
|
||||||
|
}
|
||||||
v *= 10
|
v *= 10
|
||||||
v += int(c - '0')
|
v += int(c - '0')
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDateTime(b []byte) (time.Time, error) {
|
func parseDateTime(b []byte) (time.Time, error) {
|
||||||
@@ -159,7 +171,13 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
|
|||||||
return t, nil, newDecodeError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
|
return t, nil, newDecodeError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Hour = parseDecimalDigits(b[0:2])
|
var err error
|
||||||
|
|
||||||
|
t.Hour, err = parseDecimalDigits(b[0:2])
|
||||||
|
if err != nil {
|
||||||
|
return t, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if t.Hour > 23 {
|
if t.Hour > 23 {
|
||||||
return t, nil, newDecodeError(b[0:2], "hour cannot be greater 23")
|
return t, nil, newDecodeError(b[0:2], "hour cannot be greater 23")
|
||||||
}
|
}
|
||||||
@@ -167,7 +185,10 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
|
|||||||
return t, nil, newDecodeError(b[2:3], "expecting colon between hours and minutes")
|
return t, nil, newDecodeError(b[2:3], "expecting colon between hours and minutes")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Minute = parseDecimalDigits(b[3:5])
|
t.Minute, err = parseDecimalDigits(b[3:5])
|
||||||
|
if err != nil {
|
||||||
|
return t, nil, err
|
||||||
|
}
|
||||||
if t.Minute > 59 {
|
if t.Minute > 59 {
|
||||||
return t, nil, newDecodeError(b[3:5], "minutes cannot be greater 59")
|
return t, nil, newDecodeError(b[3:5], "minutes cannot be greater 59")
|
||||||
}
|
}
|
||||||
@@ -175,7 +196,11 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
|
|||||||
return t, nil, newDecodeError(b[5:6], "expecting colon between minutes and seconds")
|
return t, nil, newDecodeError(b[5:6], "expecting colon between minutes and seconds")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Second = parseDecimalDigits(b[6:8])
|
t.Second, err = parseDecimalDigits(b[6:8])
|
||||||
|
if err != nil {
|
||||||
|
return t, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if t.Second > 59 {
|
if t.Second > 59 {
|
||||||
return t, nil, newDecodeError(b[3:5], "seconds cannot be greater 59")
|
return t, nil, newDecodeError(b[3:5], "seconds cannot be greater 59")
|
||||||
}
|
}
|
||||||
@@ -204,6 +229,10 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
|
|||||||
digits++
|
digits++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if digits == 0 {
|
||||||
|
return t, nil, newDecodeError(b[minLengthWithFrac-1:minLengthWithFrac], "nanoseconds need at least one digit")
|
||||||
|
}
|
||||||
|
|
||||||
t.Nanosecond = frac * nspow[digits]
|
t.Nanosecond = frac * nspow[digits]
|
||||||
t.Precision = digits
|
t.Precision = digits
|
||||||
|
|
||||||
|
|||||||
+29
-1
@@ -2002,7 +2002,7 @@ world'`,
|
|||||||
{
|
{
|
||||||
desc: "invalid minutes value",
|
desc: "invalid minutes value",
|
||||||
data: `a=1979-05-27T23:+2:99`,
|
data: `a=1979-05-27T23:+2:99`,
|
||||||
msg: `minutes cannot be greater 59`,
|
msg: `expected digit (0-9)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "invalid seconds value",
|
desc: "invalid seconds value",
|
||||||
@@ -2183,6 +2183,34 @@ world'`,
|
|||||||
data: `A = 2021-02-29T23:59:00`,
|
data: `A = 2021-02-29T23:59:00`,
|
||||||
msg: `impossible date`,
|
msg: `impossible date`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: `missing minute digit`,
|
||||||
|
data: `a=17:4::01`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `invalid space in year`,
|
||||||
|
data: `i=19 7-12-21T10:32:00`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `missing nanoseconds digits`,
|
||||||
|
data: `a=17:45:56.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `minutes over 60`,
|
||||||
|
data: `a=17:99:00`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `invalid second`,
|
||||||
|
data: `a=17:00::0`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `invalid hour`,
|
||||||
|
data: `a=1::00:00`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: `invalid month`,
|
||||||
|
data: `a=2021-0--29`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range examples {
|
for _, e := range examples {
|
||||||
|
|||||||
Reference in New Issue
Block a user