Decoder: check timezones start with +,-,z,Z (#688)

Also simplifies local time seconds scanning.

Fixes #686
This commit is contained in:
Thomas Pelletier
2021-11-30 13:01:15 -05:00
committed by GitHub
parent ede6445608
commit bbaae540ce
3 changed files with 21 additions and 14 deletions
+17 -13
View File
@@ -99,9 +99,14 @@ func parseDateTime(b []byte) (time.Time, error) {
if len(b) != dateTimeByteLen { if len(b) != dateTimeByteLen {
return time.Time{}, newDecodeError(b, "invalid date-time timezone") return time.Time{}, newDecodeError(b, "invalid date-time timezone")
} }
direction := 1 var direction int
if b[0] == '-' { switch b[0] {
case '-':
direction = -1 direction = -1
case '+':
direction = +1
default:
return time.Time{}, newDecodeError(b[:1], "invalid timezone offset character")
} }
hours := digitsToInt(b[1:3]) hours := digitsToInt(b[1:3])
@@ -202,26 +207,26 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
} }
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[6:8], "seconds cannot be greater 59")
} }
const minLengthWithFrac = 9 b = b[8:]
if len(b) >= minLengthWithFrac && b[minLengthWithFrac-1] == '.' {
if len(b) >= 1 && b[0] == '.' {
frac := 0 frac := 0
digits := 0 digits := 0
for i, c := range b[minLengthWithFrac:] { for i, c := range b[1:] {
if !isDigit(c) { if !isDigit(c) {
if i == 0 { if i == 0 {
return t, nil, newDecodeError(b[i:i+1], "need at least one digit after fraction point") return t, nil, newDecodeError(b[0:1], "need at least one digit after fraction point")
} }
break break
} }
const maxFracPrecision = 9 const maxFracPrecision = 9
if i >= maxFracPrecision { if i >= maxFracPrecision {
return t, nil, newDecodeError(b[i:i+1], "maximum precision for date time is nanosecond") return t, nil, newDecodeError(b[i-1:i], "maximum precision for date time is nanosecond")
} }
frac *= 10 frac *= 10
@@ -230,16 +235,15 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
} }
if digits == 0 { if digits == 0 {
return t, nil, newDecodeError(b[minLengthWithFrac-1:minLengthWithFrac], "nanoseconds need at least one digit") return t, nil, newDecodeError(b[:1], "nanoseconds need at least one digit")
} }
t.Nanosecond = frac * nspow[digits] t.Nanosecond = frac * nspow[digits]
t.Precision = digits t.Precision = digits
return t, b[9+digits:], nil return t, b[1+digits:], nil
} }
return t, b, nil
return t, b[8:], nil
} }
//nolint:cyclop //nolint:cyclop
-1
View File
@@ -862,7 +862,6 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
return p.scanIntOrFloat(b) return p.scanIntOrFloat(b)
} }
//nolint:gomnd
if len(b) < 3 { if len(b) < 3 {
return p.scanIntOrFloat(b) return p.scanIntOrFloat(b)
} }
+4
View File
@@ -2628,6 +2628,10 @@ world'`,
desc: `zero is an invalid month`, desc: `zero is an invalid month`,
data: `a=2021-00-11`, data: `a=2021-00-11`,
}, },
{
desc: `invalid number of seconds digits with trailling digit`,
data: `a=0000-01-01 00:00:000000Z3`,
},
{ {
desc: `carriage return inside basic key`, desc: `carriage return inside basic key`,
data: "\"\r\"=42", data: "\"\r\"=42",