InfluxDB: Fix regex for finding regexes in frontend code (#105194)

When interpolating variables in the frontend, we want to be sure to
escape special characters if the variable is used in a regex.

We used a regex to find regexes in raw queries, which contained a bug.
The regex treated any `/` character as the start of a regex. However,
InfluxQL (and most sql dialects) support using `/` as a division
operator.

This PR adds a check for `=~` or `!~` immediately preceding `/` as the
beginning of a regex, as per the InfluxQL spec for regexes:

https://docs.influxdata.com/influxdb/v2/reference/syntax/influxql/spec/#regular-expressions

Fixes https://github.com/grafana/support-escalations/issues/16219
pull/103937/head^2
beejeebus 1 week ago committed by GitHub
parent 0e7e0b5f29
commit 8f4b2bbece
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 20
      public/app/plugins/datasource/influxdb/datasource.test.ts
  2. 2
      public/app/plugins/datasource/influxdb/datasource.ts

@ -284,7 +284,11 @@ describe('interpolateQueryExpr', () => {
it('should return the escaped value if the value wrapped in regex', () => {
const value = '/special/path';
const variableMock = queryBuilder().withId('tempVar').withName('tempVar').withMulti(false).build();
const result = ds.interpolateQueryExpr(value, variableMock, 'select that where path = /$tempVar/');
const result = ds.interpolateQueryExpr(
value,
variableMock,
'select atan(z/sqrt(3.14)), that where path =~ /$tempVar/'
);
const expectation = `\\/special\\/path`;
expect(result).toBe(expectation);
});
@ -292,7 +296,11 @@ describe('interpolateQueryExpr', () => {
it('should return the escaped value if the value wrapped in regex 2', () => {
const value = '/special/path';
const variableMock = queryBuilder().withId('tempVar').withName('tempVar').withMulti(false).build();
const result = ds.interpolateQueryExpr(value, variableMock, 'select that where path = /^$tempVar$/');
const result = ds.interpolateQueryExpr(
value,
variableMock,
'select atan(z/sqrt(3.14)), that where path !~ /^$tempVar$/'
);
const expectation = `\\/special\\/path`;
expect(result).toBe(expectation);
});
@ -305,7 +313,11 @@ describe('interpolateQueryExpr', () => {
.withMulti(false)
.withIncludeAll(true)
.build();
const result = ds.interpolateQueryExpr(value, variableMock, 'select from /^($tempVar)$/');
const result = ds.interpolateQueryExpr(
value,
variableMock,
'select atan(z/sqrt(3.14)), thing from path =~ /^($tempVar)$/'
);
const expectation = `(env|env2|env3)`;
expect(result).toBe(expectation);
});
@ -358,7 +370,7 @@ describe('interpolateQueryExpr', () => {
)
.build();
const value = [`/special/path`, `/some/other/path`];
const result = ds.interpolateQueryExpr(value, variableMock, `select that where path = /$tempVar/`);
const result = ds.interpolateQueryExpr(value, variableMock, `select that where path =~ /$tempVar/`);
const expectation = `(\\/special\\/path|\\/some\\/other\\/path)`;
expect(result).toBe(expectation);
});

@ -353,7 +353,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
// we escape it. Otherwise, we return it directly.
// The regex below searches for regexes within the query string
const regexMatcher = new RegExp(
/\/((?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+)\/((?:g(?:im?|mi?)?|i(?:gm?|mg?)?|m(?:gi?|ig?)?)?)/,
/(\s*(=|!)~\s*)\/((?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+)\/((?:g(?:im?|mi?)?|i(?:gm?|mg?)?|m(?:gi?|ig?)?)?)/,
'gm'
);
// If matches are found this regex is evaluated to check if the variable is contained in the regex /^...$/ (^ and $ is optional)

Loading…
Cancel
Save