mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Re-work unescaping arguments in parser
Related issue: https://github.com/uBlockOrigin/uAssets/issues/5184#issuecomment-1803455520
This commit is contained in:
parent
2bc7996d64
commit
ec53a8f2c7
@ -599,11 +599,6 @@ const exCharCodeAt = (s, i) => {
|
||||
return pos >= 0 ? s.charCodeAt(pos) : -1;
|
||||
};
|
||||
|
||||
const toEscapedCharRegex = c => {
|
||||
const safe = c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
return new RegExp(`((?:^|[^\\\\])(?:\\\\\\\\)*)\\\\${safe}`, 'g');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class ArgListParser {
|
||||
@ -619,11 +614,7 @@ class ArgListParser {
|
||||
this.reWhitespaceStart = /^\s+/;
|
||||
this.reWhitespaceEnd = /\s+$/;
|
||||
this.reOddTrailingEscape = /(?:^|[^\\])(?:\\\\)*\\$/;
|
||||
this.reEscapedDoubleQuote = toEscapedCharRegex('"');
|
||||
this.reEscapedSingleQuote = toEscapedCharRegex("'");
|
||||
this.reEscapedBacktick = toEscapedCharRegex('`');
|
||||
this.reEscapedSeparator = toEscapedCharRegex(this.separatorChar);
|
||||
this.unescapedSeparator = `$1${this.separatorChar}`;
|
||||
this.reTrailingEscapeChars = /\\+$/;
|
||||
}
|
||||
nextArg(pattern, beg = 0) {
|
||||
const len = pattern.length;
|
||||
@ -655,22 +646,23 @@ class ArgListParser {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
normalizeArg(s) {
|
||||
switch ( this.actualSeparatorCode ) {
|
||||
case 0x22 /* " */:
|
||||
if ( s.includes('"') === false ) { return; }
|
||||
return s.replace(this.reEscapedDoubleQuote, '$1"');
|
||||
case 0x27 /* ' */:
|
||||
if ( s.includes("'") === false ) { return; }
|
||||
return s.replace(this.reEscapedSingleQuote, "$1'");
|
||||
case 0x60 /* ` */:
|
||||
if ( s.includes('`') === false ) { return; }
|
||||
return s.replace(this.reEscapedBacktick, '$1`');
|
||||
default:
|
||||
break;
|
||||
normalizeArg(s, char = '') {
|
||||
if ( char === '' ) { char = this.actualSeparatorChar; }
|
||||
let out = '';
|
||||
let pos = 0;
|
||||
while ( (pos = s.lastIndexOf(char)) !== -1 ) {
|
||||
out = s.slice(pos) + out;
|
||||
s = s.slice(0, pos);
|
||||
const match = this.reTrailingEscapeChars.exec(s);
|
||||
if ( match === null ) { continue; }
|
||||
const tail = (match[0].length & 1) !== 0
|
||||
? match[0].slice(0, -1)
|
||||
: match[0];
|
||||
out = tail + out;
|
||||
s = s.slice(0, -match[0].length);
|
||||
}
|
||||
if ( s.includes(this.separatorChar) === false ) { return; }
|
||||
return s.replace(this.reEscapedSeparator, this.unescapedSeparator);
|
||||
if ( out === '' ) { return s; }
|
||||
return s + out;
|
||||
}
|
||||
leftWhitespaceCount(s) {
|
||||
const match = this.reWhitespaceStart.exec(s);
|
||||
@ -3006,7 +2998,6 @@ export function parseHeaderValue(arg) {
|
||||
|
||||
export function parseReplaceValue(s) {
|
||||
if ( s.charCodeAt(0) !== 0x2F /* / */ ) { return; }
|
||||
const { reEscapedComma, reEscapedDollarSign } = parseReplaceValue;
|
||||
const parser = new ArgListParser('/');
|
||||
parser.nextArg(s, 1);
|
||||
let pattern = s.slice(parser.argBeg, parser.argEnd);
|
||||
@ -3014,26 +3005,22 @@ export function parseReplaceValue(s) {
|
||||
pattern = parser.normalizeArg(pattern);
|
||||
}
|
||||
if ( pattern === '' ) { return; }
|
||||
pattern = pattern
|
||||
.replace(reEscapedDollarSign, '$1$$$')
|
||||
.replace(reEscapedComma, '$1,');
|
||||
pattern = parser.normalizeArg(pattern, '$');
|
||||
pattern = parser.normalizeArg(pattern, ',');
|
||||
parser.nextArg(s, parser.separatorEnd);
|
||||
let replacement = s.slice(parser.argBeg, parser.argEnd);
|
||||
if ( parser.separatorEnd === parser.separatorBeg ) { return; }
|
||||
if ( parser.transform ) {
|
||||
replacement = parser.normalizeArg(replacement);
|
||||
}
|
||||
replacement = replacement
|
||||
.replace(reEscapedDollarSign, '$1$$')
|
||||
.replace(reEscapedComma, '$1,');
|
||||
replacement = parser.normalizeArg(replacement, '$');
|
||||
replacement = parser.normalizeArg(replacement, ',');
|
||||
const flags = s.slice(parser.separatorEnd);
|
||||
try {
|
||||
return { re: new RegExp(pattern, flags), replacement };
|
||||
} catch(_) {
|
||||
}
|
||||
}
|
||||
parseReplaceValue.reEscapedDollarSign = toEscapedCharRegex('$');
|
||||
parseReplaceValue.reEscapedComma = toEscapedCharRegex(',');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user