Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix duration overflow detection #54

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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