Skip to content

Commit 4a508be

Browse files
committed
fix duration overflow detection
1 parent 1ba4703 commit 4a508be

File tree

2 files changed

+35
-27
lines changed

2 files changed

+35
-27
lines changed

parser.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e
10691069
stmt.Database = lit
10701070
} else if tok == MUL {
10711071
stmt.WildcardDatabase = true
1072-
} else{
1072+
} else {
10731073
return nil, newParseError(tokstr(tok, lit), []string{"identifier or *"}, pos)
10741074
}
10751075

@@ -1079,7 +1079,7 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e
10791079
stmt.RetentionPolicy = lit
10801080
} else if tok == MUL {
10811081
stmt.WildcardRetentionPolicy = true
1082-
} else{
1082+
} else {
10831083
return nil, newParseError(tokstr(tok, lit), []string{"identifier or *"}, pos)
10841084
}
10851085
} else {
@@ -2995,8 +2995,8 @@ func ParseDuration(s string) (time.Duration, error) {
29952995
i++
29962996
}
29972997

2998-
var measure int64
29992998
var unit string
2999+
var unitDuration time.Duration
30003000

30013001
// Parsing loop.
30023002
for i < len(a) {
@@ -3016,7 +3016,6 @@ func ParseDuration(s string) (time.Duration, error) {
30163016
if err != nil {
30173017
return 0, ErrInvalidDuration
30183018
}
3019-
measure = n
30203019

30213020
// Extract the unit of measure.
30223021
// If the last two characters are "ms" then parse as milliseconds.
@@ -3026,40 +3025,41 @@ func ParseDuration(s string) (time.Duration, error) {
30263025
case 'n':
30273026
if i+1 < len(a) && a[i+1] == 's' {
30283027
unit = string(a[i : i+2])
3029-
d += time.Duration(n)
3030-
i += 2
3031-
continue
3028+
unitDuration = time.Nanosecond
3029+
break
30323030
}
30333031
return 0, ErrInvalidDuration
30343032
case 'u', 'µ':
3035-
d += time.Duration(n) * time.Microsecond
3033+
unitDuration = time.Microsecond
30363034
case 'm':
30373035
if i+1 < len(a) && a[i+1] == 's' {
30383036
unit = string(a[i : i+2])
3039-
d += time.Duration(n) * time.Millisecond
3040-
i += 2
3041-
continue
3037+
unitDuration = time.Millisecond
3038+
break
30423039
}
3043-
d += time.Duration(n) * time.Minute
3040+
unitDuration = time.Minute
30443041
case 's':
3045-
d += time.Duration(n) * time.Second
3042+
unitDuration = time.Second
30463043
case 'h':
3047-
d += time.Duration(n) * time.Hour
3044+
unitDuration = time.Hour
30483045
case 'd':
3049-
d += time.Duration(n) * 24 * time.Hour
3046+
unitDuration = 24 * time.Hour
30503047
case 'w':
3051-
d += time.Duration(n) * 7 * 24 * time.Hour
3048+
unitDuration = 7 * 24 * time.Hour
30523049
default:
30533050
return 0, ErrInvalidDuration
30543051
}
3055-
i++
3056-
}
3057-
3058-
// Check to see if we overflowed a duration
3059-
if d < 0 && !isNegative {
3060-
return 0, fmt.Errorf("overflowed duration %d%s: choose a smaller duration or INF", measure, unit)
3052+
// Check to see if we overflowed a duration
3053+
if n > (1<<63-1)/unitDuration.Nanoseconds() {
3054+
return 0, fmt.Errorf("overflowed duration %s: choose a smaller duration or INF", s)
3055+
}
3056+
d += time.Duration(n) * unitDuration
3057+
// Check to see if we overflowed a duration
3058+
if d < 0 {
3059+
return 0, fmt.Errorf("overflowed duration %s: choose a smaller duration or INF", s)
3060+
}
3061+
i += len(unit)
30613062
}
3062-
30633063
if isNegative {
30643064
d = -d
30653065
}

parser_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,7 +1957,7 @@ func TestParser_ParseStatement(t *testing.T) {
19571957
{
19581958
s: `SHOW MEASUREMENTS ON db0.rp0`,
19591959
stmt: &influxql.ShowMeasurementsStatement{
1960-
Database: "db0",
1960+
Database: "db0",
19611961
RetentionPolicy: "rp0",
19621962
},
19631963
},
@@ -1974,7 +1974,7 @@ func TestParser_ParseStatement(t *testing.T) {
19741974
{
19751975
s: `SHOW MEASUREMENTS ON *.*`,
19761976
stmt: &influxql.ShowMeasurementsStatement{
1977-
WildcardDatabase: true,
1977+
WildcardDatabase: true,
19781978
WildcardRetentionPolicy: true,
19791979
},
19801980
},
@@ -1983,7 +1983,7 @@ func TestParser_ParseStatement(t *testing.T) {
19831983
{
19841984
s: `SHOW MEASUREMENTS ON db0.*`,
19851985
stmt: &influxql.ShowMeasurementsStatement{
1986-
Database: "db0",
1986+
Database: "db0",
19871987
WildcardRetentionPolicy: true,
19881988
},
19891989
},
@@ -1992,7 +1992,7 @@ func TestParser_ParseStatement(t *testing.T) {
19921992
{
19931993
s: `SHOW MEASUREMENTS ON *.rp0`,
19941994
stmt: &influxql.ShowMeasurementsStatement{
1995-
RetentionPolicy: "rp0",
1995+
RetentionPolicy: "rp0",
19961996
WildcardDatabase: true,
19971997
},
19981998
},
@@ -4171,6 +4171,10 @@ func TestParseDuration(t *testing.T) {
41714171
{s: `1.2w`, err: "invalid duration"},
41724172
{s: `10x`, err: "invalid duration"},
41734173
{s: `10n`, err: "invalid duration"},
4174+
4175+
{s: `99999999999h`, err: overflowErrString(`99999999999h`)},
4176+
{s: `2562047h50m`, err: overflowErrString(`2562047h50m`)},
4177+
{s: `-2562047h47m50s`, err: overflowErrString(`-2562047h47m50s`)},
41744178
}
41754179

41764180
for i, tt := range tests {
@@ -4183,6 +4187,10 @@ func TestParseDuration(t *testing.T) {
41834187
}
41844188
}
41854189

4190+
func overflowErrString(s string) string {
4191+
return fmt.Sprintf("overflowed duration %s: choose a smaller duration or INF", s)
4192+
}
4193+
41864194
// Ensure a time duration can be formatted.
41874195
func TestFormatDuration(t *testing.T) {
41884196
var tests = []struct {

0 commit comments

Comments
 (0)