Skip to content

Commit

Permalink
ts: Fix nil pointer panic on invalid TS query
Browse files Browse the repository at this point in the history
A query which specified an invalid enumeration value for
SourceAggregator would cause a nil pointer panic on the server.
Repaired this fix and added a test for invalid values of all the
enumeration values of the query request.

Fixes cockroachdb#23766

Release note: None
  • Loading branch information
Matt Tracy committed Mar 13, 2018
1 parent 41f9808 commit 0ec041d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
10 changes: 6 additions & 4 deletions pkg/ts/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,10 @@ func (db *DB) Query(
aggFn = aggregatingIterator.max
case tspb.TimeSeriesQueryAggregator_MIN:
aggFn = aggregatingIterator.min
default:
return nil, nil, fmt.Errorf(
"query specified unknown time series aggregator: %s", query.GetSourceAggregator().String(),
)
}

// Filter the result of the aggregation function through a leading edge
Expand Down Expand Up @@ -1124,7 +1128,6 @@ func makeDataSpans(
return sourceSpans, nil
}

// getExtractionFunction returns
func getExtractionFunction(agg tspb.TimeSeriesQueryAggregator) (extractFn, error) {
switch agg {
case tspb.TimeSeriesQueryAggregator_AVG:
Expand All @@ -1136,7 +1139,7 @@ func getExtractionFunction(agg tspb.TimeSeriesQueryAggregator) (extractFn, error
case tspb.TimeSeriesQueryAggregator_MIN:
return (roachpb.InternalTimeSeriesSample).Minimum, nil
}
return nil, errors.Errorf("query specified unknown time series aggregator %s", agg.String())
return nil, errors.Errorf("query specified unknown time series downsampler %s", agg.String())
}

func downsampleSum(points ...roachpb.InternalTimeSeriesSample) float64 {
Expand Down Expand Up @@ -1177,7 +1180,6 @@ func downsampleAvg(points ...roachpb.InternalTimeSeriesSample) float64 {
return total / float64(count)
}

// getDownsampleFunction returns
func getDownsampleFunction(agg tspb.TimeSeriesQueryAggregator) (downsampleFn, error) {
switch agg {
case tspb.TimeSeriesQueryAggregator_AVG:
Expand All @@ -1189,5 +1191,5 @@ func getDownsampleFunction(agg tspb.TimeSeriesQueryAggregator) (downsampleFn, er
case tspb.TimeSeriesQueryAggregator_MIN:
return downsampleMin, nil
}
return nil, errors.Errorf("query specified unknown time series aggregator %s", agg.String())
return nil, errors.Errorf("query specified unknown time series downsampler %s", agg.String())
}
57 changes: 57 additions & 0 deletions pkg/ts/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1494,3 +1494,60 @@ func TestQueryWorkerMemoryMonitor(t *testing.T) {
t.Logf("total allocations for query: %d\n", memStatsAfter.TotalAlloc-memStatsBefore.TotalAlloc)
t.Logf("maximum allocations for query monitor: %d\n", limitedMon.MaximumBytes())
}

// TestQueryBadRequests confirms that the query method returns gentle errors for
// obviously bad incoming data.
func TestQueryBadRequests(t *testing.T) {
defer leaktest.AfterTest(t)()
tm := newTestModel(t)
tm.Start()
defer tm.Stop()

account := tm.workerMemMonitor.MakeBoundAccount()
defer account.Close(context.TODO())

// Query with a downsampler that is invalid, expect error.
downsampler := (tspb.TimeSeriesQueryAggregator)(999)
_, _, err := tm.DB.Query(
context.TODO(), tspb.Query{
Name: "metric.test",
Downsampler: downsampler.Enum(),
}, resolution1ns, 10, 0, 10000, 0, &account, tm.workerMemMonitor,
)
errorStr := "unknown time series downsampler"
if !testutils.IsError(err, errorStr) {
if err == nil {
t.Fatalf("bad query got no error, wanted to match %q", errorStr)
} else {
t.Fatalf("bad query got error %q, wanted to match %q", err.Error(), errorStr)
}
}

// Query with a aggregator that is invalid, expect error.
aggregator := (tspb.TimeSeriesQueryAggregator)(999)
_, _, err = tm.DB.Query(
context.TODO(), tspb.Query{
Name: "metric.test",
SourceAggregator: aggregator.Enum(),
}, resolution1ns, 10, 0, 10000, 0, &account, tm.workerMemMonitor,
)
errorStr = "unknown time series aggregator"
if !testutils.IsError(err, errorStr) {
if err == nil {
t.Fatalf("bad query got no error, wanted to match %q", errorStr)
} else {
t.Fatalf("bad query got error %q, wanted to match %q", err.Error(), errorStr)
}
}

// Query with an interpolator that is invalid, expect no error (default behavior is none).
derivative := (tspb.TimeSeriesQueryDerivative)(999)
_, _, err = tm.DB.Query(
context.TODO(), tspb.Query{
Derivative: derivative.Enum(),
}, resolution1ns, 10, 0, 10000, 0, &account, tm.workerMemMonitor,
)
if !testutils.IsError(err, "") {
t.Fatalf("bad query got error %q, wanted no error", err.Error())
}
}

0 comments on commit 0ec041d

Please sign in to comment.