mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
packages/grafana-data/text: Improve escaping for special characters (#47066)
FilterInput escapes all input strings for special characters that might be used in a RegExp by calling escapeStringForRegex, and using unEscapeStringFromRegex for display. Both of these functions used string.prototype.replace() for escaping. replace() only replaces the first occurence of a search string unless called with a global RegExp. The output of these functions was not necessarily safe to compile into a RegExp literal. This change creates RegExps for escapeStringForRegex and unEscapeStringFromRegex to match all occurrences of the special characters instead of just their first occurrence. This makes a variety of strings safe for RegExp compilation.
This commit is contained in:
parent
5a87d12e8c
commit
c5cfc1645a
@ -57,12 +57,32 @@ describe('stringToMs', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('[un]escapeStringForRegex', () => {
|
||||||
|
it.each([
|
||||||
|
'[]',
|
||||||
|
'\\',
|
||||||
|
'[(abc])',
|
||||||
|
'onetwothree',
|
||||||
|
'<namedgroup}(this is not a regex>',
|
||||||
|
'string\\with\\backslash',
|
||||||
|
'everyspecialchar([{])}.,/?&*-^&<>#',
|
||||||
|
])('should be symmetric', (input) => {
|
||||||
|
const output = unEscapeStringFromRegex(escapeStringForRegex(input));
|
||||||
|
expect(output).toEqual(input);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('escapeStringForRegex', () => {
|
describe('escapeStringForRegex', () => {
|
||||||
describe('when using a string with special chars', () => {
|
it.each([
|
||||||
it('then all special chars should be escaped', () => {
|
'[[[',
|
||||||
const result = escapeStringForRegex('([{}])|*+-.?<>#&^$');
|
'[]\\',
|
||||||
expect(result).toBe('\\(\\[\\{\\}\\]\\)\\|\\*\\+\\-\\.\\?\\<\\>\\#\\&\\^\\$');
|
'[(abc])',
|
||||||
});
|
'onetwothree',
|
||||||
|
'<namedgroup}(this is not a regex>',
|
||||||
|
'string\\with\\backslash',
|
||||||
|
'everyspecialchar([{])}.,/?&*-^&<>#',
|
||||||
|
])('should always produce output that compiles', (value) => {
|
||||||
|
expect(() => new RegExp(escapeStringForRegex(value))).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when using a string without special chars', () => {
|
describe('when using a string without special chars', () => {
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
const specialChars = ['(', '[', '{', '}', ']', ')', '|', '*', '+', '-', '.', '?', '<', '>', '#', '&', '^', '$'];
|
|
||||||
|
const specialChars = ['(', '[', '{', '}', ']', ')', '\\', '|', '*', '+', '-', '.', '?', '<', '>', '#', '&', '^', '$'];
|
||||||
|
const specialMatcher = '([\\' + specialChars.join('\\') + '])';
|
||||||
|
const specialCharEscape = new RegExp(specialMatcher, 'g');
|
||||||
|
const specialCharUnescape = new RegExp('(\\\\)' + specialMatcher, 'g');
|
||||||
|
|
||||||
export const escapeStringForRegex = (value: string) => {
|
export const escapeStringForRegex = (value: string) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return specialChars.reduce((escaped, currentChar) => escaped.replace(currentChar, '\\' + currentChar), value);
|
return value.replace(specialCharEscape, '\\$1');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unEscapeStringFromRegex = (value: string) => {
|
export const unEscapeStringFromRegex = (value: string) => {
|
||||||
@ -14,7 +18,7 @@ export const unEscapeStringFromRegex = (value: string) => {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return specialChars.reduce((escaped, currentChar) => escaped.replace('\\' + currentChar, currentChar), value);
|
return value.replace(specialCharUnescape, '$2');
|
||||||
};
|
};
|
||||||
|
|
||||||
export function stringStartsAsRegEx(str: string): boolean {
|
export function stringStartsAsRegEx(str: string): boolean {
|
||||||
|
Loading…
Reference in New Issue
Block a user