Decoder: check timezones start with +,-,z,Z (#688)
Also simplifies local time seconds scanning. Fixes #686
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user