Skip to content

Commit

Permalink
Decode: add missing checks for LocalTime (#650)
Browse files Browse the repository at this point in the history
  • Loading branch information
pelletier authored Oct 30, 2021
1 parent 772d169 commit 85c0658
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 11 deletions.
49 changes: 39 additions & 10 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,22 @@ func parseLocalDate(b []byte) (LocalDate, error) {
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) {
return LocalDate{}, newDecodeError(b, "impossible date")
Expand All @@ -50,15 +59,18 @@ func parseLocalDate(b []byte) (LocalDate, error) {
return date, nil
}

func parseDecimalDigits(b []byte) int {
func parseDecimalDigits(b []byte) (int, error) {
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 += int(c - '0')
}

return v
return v, nil
}

func parseDateTime(b []byte) (time.Time, error) {
Expand Down Expand Up @@ -159,23 +171,36 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
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 {
return t, nil, newDecodeError(b[0:2], "hour cannot be greater 23")
}
if b[2] != ':' {
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 {
return t, nil, newDecodeError(b[3:5], "minutes cannot be greater 59")
}
if b[5] != ':' {
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 {
return t, nil, newDecodeError(b[3:5], "seconds cannot be greater 59")
}
Expand Down Expand Up @@ -204,6 +229,10 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
digits++
}

if digits == 0 {
return t, nil, newDecodeError(b[minLengthWithFrac-1:minLengthWithFrac], "nanoseconds need at least one digit")
}

t.Nanosecond = frac * nspow[digits]
t.Precision = digits

Expand Down
30 changes: 29 additions & 1 deletion unmarshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2002,7 +2002,7 @@ world'`,
{
desc: "invalid minutes value",
data: `a=1979-05-27T23:+2:99`,
msg: `minutes cannot be greater 59`,
msg: `expected digit (0-9)`,
},
{
desc: "invalid seconds value",
Expand Down Expand Up @@ -2183,6 +2183,34 @@ world'`,
data: `A = 2021-02-29T23:59:00`,
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 {
Expand Down

0 comments on commit 85c0658

Please sign in to comment.