From 2b1074539cb247e9d67d144dfc25698d8f77b678 Mon Sep 17 00:00:00 2001 From: davidby-influx <72418212+davidby-influx@users.noreply.github.com> Date: Wed, 27 Oct 2021 11:47:37 -0700 Subject: [PATCH] fix: detect misquoted tag values and return an error (#22754) (#22781) SHOW TAG KEYS FROM "foo" where bar="misquoted" is erroneous, because the tag value must be enclosed in single, not double, quotes. Although this correctly returns no tag keys, it is very inefficient and has cause out-of-memory failures at a customer. This fix short-circuits the query. closes https://github.com/influxdata/influxdb/issues/22755 (cherry picked from commit af9e89a4d46b7f83623b3cdd5996fcccc39609e8) closes https://github.com/influxdata/influxdb/issues/22756 --- tsdb/store.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tsdb/store.go b/tsdb/store.go index 837422d0dd6..bce30a37d6f 100644 --- a/tsdb/store.go +++ b/tsdb/store.go @@ -1640,6 +1640,9 @@ func (s *Store) TagKeys(ctx context.Context, auth query.FineAuthorizer, shardIDs if err != nil { return nil, err } + if err = isBadQuoteTagValueClause(filterExpr); err != nil { + return nil, err + } // Get all the shards we're interested in. is := IndexSet{Indexes: make([]Index, 0, len(shardIDs))} @@ -1808,6 +1811,31 @@ func isTagKeyClause(e influxql.Expr) (bool, error) { return false, nil } +func isBadQuoteTagValueClause(e influxql.Expr) error { + switch e := e.(type) { + case *influxql.BinaryExpr: + switch e.Op { + case influxql.EQ, influxql.NEQ: + _, lOk := e.LHS.(*influxql.VarRef) + _, rOk := e.RHS.(*influxql.VarRef) + if lOk && rOk { + return fmt.Errorf("bad WHERE clause for metaquery; one term must be a string literal tag value within single quotes: %s", e.String()) + } + case influxql.OR, influxql.AND: + if err := isBadQuoteTagValueClause(e.LHS); err != nil { + return err + } else if err = isBadQuoteTagValueClause(e.RHS); err != nil { + return err + } else { + return nil + } + } + case *influxql.ParenExpr: + return isBadQuoteTagValueClause(e.Expr) + } + return nil +} + // TagValues returns the tag keys and values for the provided shards, where the // tag values satisfy the provided condition. func (s *Store) TagValues(ctx context.Context, auth query.FineAuthorizer, shardIDs []uint64, cond influxql.Expr) ([]TagValues, error) { @@ -1842,7 +1870,9 @@ func (s *Store) TagValues(ctx context.Context, auth query.FineAuthorizer, shardI if err != nil { return nil, err } - + if err = isBadQuoteTagValueClause(filterExpr); err != nil { + return nil, err + } // Build index set to work on. is := IndexSet{Indexes: make([]Index, 0, len(shardIDs))} s.mu.RLock()