Parcourir la source

Fix #10555 #6888 Better escape for Prometheus variables

Prior this commit, C:\bar was escaped C:\\\bar. Should be C:\\\\bar.

Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
Julien Pivotto il y a 7 ans
Parent
commit
1f1719c498

+ 7 - 3
public/app/plugins/datasource/prometheus/datasource.ts

@@ -6,8 +6,12 @@ import * as dateMath from 'app/core/utils/datemath';
 import PrometheusMetricFindQuery from './metric_find_query';
 import { ResultTransformer } from './result_transformer';
 
-function prometheusSpecialRegexEscape(value) {
-  return value.replace(/[\\^$*+?.()|[\]{}]/g, '\\\\$&');
+export function prometheusRegularEscape(value) {
+  return value.replace(/'/g, "\\\\'");
+}
+
+export function prometheusSpecialRegexEscape(value) {
+  return prometheusRegularEscape(value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]+?.()]/g, '\\\\$&'));
 }
 
 export class PrometheusDatasource {
@@ -80,7 +84,7 @@ export class PrometheusDatasource {
   interpolateQueryExpr(value, variable, defaultFormatFn) {
     // if no multi or include all do not regexEscape
     if (!variable.multi && !variable.includeAll) {
-      return value;
+      return prometheusRegularEscape(value);
     }
 
     if (typeof value === 'string') {

+ 38 - 1
public/app/plugins/datasource/prometheus/specs/datasource.jest.ts

@@ -1,7 +1,7 @@
 import _ from 'lodash';
 import moment from 'moment';
 import q from 'q';
-import { PrometheusDatasource } from '../datasource';
+import { PrometheusDatasource, prometheusSpecialRegexEscape, prometheusRegularEscape } from '../datasource';
 
 describe('PrometheusDatasource', () => {
   let ctx: any = {};
@@ -101,4 +101,41 @@ describe('PrometheusDatasource', () => {
       });
     });
   });
+
+  describe('Prometheus regular escaping', function() {
+    it('should not escape simple string', function() {
+      expect(prometheusRegularEscape('cryptodepression')).toEqual('cryptodepression');
+    });
+    it("should escape '", function() {
+      expect(prometheusRegularEscape("looking'glass")).toEqual("looking\\\\'glass");
+    });
+    it('should escape multiple characters', function() {
+      expect(prometheusRegularEscape("'looking'glass'")).toEqual("\\\\'looking\\\\'glass\\\\'");
+    });
+  });
+
+  describe('Prometheus regexes escaping', function() {
+    it('should not escape simple string', function() {
+      expect(prometheusSpecialRegexEscape('cryptodepression')).toEqual('cryptodepression');
+    });
+    it('should escape $^*+?.()\\', function() {
+      expect(prometheusSpecialRegexEscape("looking'glass")).toEqual("looking\\\\'glass");
+      expect(prometheusSpecialRegexEscape('looking{glass')).toEqual('looking\\\\{glass');
+      expect(prometheusSpecialRegexEscape('looking}glass')).toEqual('looking\\\\}glass');
+      expect(prometheusSpecialRegexEscape('looking[glass')).toEqual('looking\\\\[glass');
+      expect(prometheusSpecialRegexEscape('looking]glass')).toEqual('looking\\\\]glass');
+      expect(prometheusSpecialRegexEscape('looking$glass')).toEqual('looking\\\\$glass');
+      expect(prometheusSpecialRegexEscape('looking^glass')).toEqual('looking\\\\^glass');
+      expect(prometheusSpecialRegexEscape('looking*glass')).toEqual('looking\\\\*glass');
+      expect(prometheusSpecialRegexEscape('looking+glass')).toEqual('looking\\\\+glass');
+      expect(prometheusSpecialRegexEscape('looking?glass')).toEqual('looking\\\\?glass');
+      expect(prometheusSpecialRegexEscape('looking.glass')).toEqual('looking\\\\.glass');
+      expect(prometheusSpecialRegexEscape('looking(glass')).toEqual('looking\\\\(glass');
+      expect(prometheusSpecialRegexEscape('looking)glass')).toEqual('looking\\\\)glass');
+      expect(prometheusSpecialRegexEscape('looking\\glass')).toEqual('looking\\\\\\\\glass');
+    });
+    it('should escape multiple special characters', function() {
+      expect(prometheusSpecialRegexEscape('+looking$glass?')).toEqual('\\\\+looking\\\\$glass\\\\?');
+    });
+  });
 });