Skip to content

Commit

Permalink
fix duration overflow detection
Browse files Browse the repository at this point in the history
  • Loading branch information
Sniper91 committed Oct 17, 2022
1 parent 1ba4703 commit 4a508be
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
46 changes: 23 additions & 23 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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.
Expand All @@ -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
}
Expand Down
16 changes: 12 additions & 4 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
},
Expand All @@ -1974,7 +1974,7 @@ func TestParser_ParseStatement(t *testing.T) {
{
s: `SHOW MEASUREMENTS ON *.*`,
stmt: &influxql.ShowMeasurementsStatement{
WildcardDatabase: true,
WildcardDatabase: true,
WildcardRetentionPolicy: true,
},
},
Expand All @@ -1983,7 +1983,7 @@ func TestParser_ParseStatement(t *testing.T) {
{
s: `SHOW MEASUREMENTS ON db0.*`,
stmt: &influxql.ShowMeasurementsStatement{
Database: "db0",
Database: "db0",
WildcardRetentionPolicy: true,
},
},
Expand All @@ -1992,7 +1992,7 @@ func TestParser_ParseStatement(t *testing.T) {
{
s: `SHOW MEASUREMENTS ON *.rp0`,
stmt: &influxql.ShowMeasurementsStatement{
RetentionPolicy: "rp0",
RetentionPolicy: "rp0",
WildcardDatabase: true,
},
},
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down

0 comments on commit 4a508be

Please sign in to comment.