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