diff --git a/parser.go b/parser.go index d7a5d0b..55dd3dc 100644 --- a/parser.go +++ b/parser.go @@ -1069,7 +1069,7 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e stmt.Database = lit } else if tok == MUL { stmt.WildcardDatabase = true - } else{ + } else { return nil, newParseError(tokstr(tok, lit), []string{"identifier or *"}, pos) } @@ -1079,7 +1079,7 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e stmt.RetentionPolicy = lit } else if tok == MUL { stmt.WildcardRetentionPolicy = true - } else{ + } else { return nil, newParseError(tokstr(tok, lit), []string{"identifier or *"}, pos) } } else { @@ -2995,8 +2995,8 @@ func ParseDuration(s string) (time.Duration, error) { i++ } - var measure int64 var unit string + var unitDuration time.Duration // Parsing loop. for i < len(a) { @@ -3016,7 +3016,6 @@ func ParseDuration(s string) (time.Duration, error) { if err != nil { return 0, ErrInvalidDuration } - measure = n // Extract the unit of measure. // If the last two characters are "ms" then parse as milliseconds. @@ -3026,40 +3025,41 @@ func ParseDuration(s string) (time.Duration, error) { case 'n': if i+1 < len(a) && a[i+1] == 's' { unit = string(a[i : i+2]) - d += time.Duration(n) - i += 2 - continue + unitDuration = time.Nanosecond + break } return 0, ErrInvalidDuration case 'u', 'ยต': - d += time.Duration(n) * time.Microsecond + unitDuration = time.Microsecond case 'm': if i+1 < len(a) && a[i+1] == 's' { unit = string(a[i : i+2]) - d += time.Duration(n) * time.Millisecond - i += 2 - continue + unitDuration = time.Millisecond + break } - d += time.Duration(n) * time.Minute + unitDuration = time.Minute case 's': - d += time.Duration(n) * time.Second + unitDuration = time.Second case 'h': - d += time.Duration(n) * time.Hour + unitDuration = time.Hour case 'd': - d += time.Duration(n) * 24 * time.Hour + unitDuration = 24 * time.Hour case 'w': - d += time.Duration(n) * 7 * 24 * time.Hour + unitDuration = 7 * 24 * time.Hour default: return 0, ErrInvalidDuration } - i++ - } - - // Check to see if we overflowed a duration - if d < 0 && !isNegative { - return 0, fmt.Errorf("overflowed duration %d%s: choose a smaller duration or INF", measure, unit) + // Check to see if we overflowed a duration + if n > (1<<63-1)/unitDuration.Nanoseconds() { + return 0, fmt.Errorf("overflowed duration %s: choose a smaller duration or INF", s) + } + d += time.Duration(n) * unitDuration + // Check to see if we overflowed a duration + if d < 0 { + return 0, fmt.Errorf("overflowed duration %s: choose a smaller duration or INF", s) + } + i += len(unit) } - if isNegative { d = -d } diff --git a/parser_test.go b/parser_test.go index e425694..d2cf9ba 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1957,7 +1957,7 @@ func TestParser_ParseStatement(t *testing.T) { { s: `SHOW MEASUREMENTS ON db0.rp0`, stmt: &influxql.ShowMeasurementsStatement{ - Database: "db0", + Database: "db0", RetentionPolicy: "rp0", }, }, @@ -1974,7 +1974,7 @@ func TestParser_ParseStatement(t *testing.T) { { s: `SHOW MEASUREMENTS ON *.*`, stmt: &influxql.ShowMeasurementsStatement{ - WildcardDatabase: true, + WildcardDatabase: true, WildcardRetentionPolicy: true, }, }, @@ -1983,7 +1983,7 @@ func TestParser_ParseStatement(t *testing.T) { { s: `SHOW MEASUREMENTS ON db0.*`, stmt: &influxql.ShowMeasurementsStatement{ - Database: "db0", + Database: "db0", WildcardRetentionPolicy: true, }, }, @@ -1992,7 +1992,7 @@ func TestParser_ParseStatement(t *testing.T) { { s: `SHOW MEASUREMENTS ON *.rp0`, stmt: &influxql.ShowMeasurementsStatement{ - RetentionPolicy: "rp0", + RetentionPolicy: "rp0", WildcardDatabase: true, }, }, @@ -4171,6 +4171,10 @@ func TestParseDuration(t *testing.T) { {s: `1.2w`, err: "invalid duration"}, {s: `10x`, err: "invalid duration"}, {s: `10n`, err: "invalid duration"}, + + {s: `99999999999h`, err: overflowErrString(`99999999999h`)}, + {s: `2562047h50m`, err: overflowErrString(`2562047h50m`)}, + {s: `-2562047h47m50s`, err: overflowErrString(`-2562047h47m50s`)}, } for i, tt := range tests { @@ -4183,6 +4187,10 @@ func TestParseDuration(t *testing.T) { } } +func overflowErrString(s string) string { + return fmt.Sprintf("overflowed duration %s: choose a smaller duration or INF", s) +} + // Ensure a time duration can be formatted. func TestFormatDuration(t *testing.T) { var tests = []struct {