1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-15 15:32:28 +02:00

Ignore !#include directives within inactive !#if/!#endif blocks

Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/1113
This commit is contained in:
Raymond Hill 2020-07-03 08:43:40 -04:00
parent ae57affea5
commit aab3812089
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 99 additions and 78 deletions

View File

@ -244,6 +244,7 @@ api.fetchFilterList = async function(mainlistURL) {
const sublistURLs = new Set(); const sublistURLs = new Set();
// https://github.com/uBlockOrigin/uBlock-issues/issues/1113
const processIncludeDirectives = function(results) { const processIncludeDirectives = function(results) {
const out = []; const out = [];
const reInclude = /^!#include +(\S+)/gm; const reInclude = /^!#include +(\S+)/gm;
@ -254,28 +255,36 @@ api.fetchFilterList = async function(mainlistURL) {
} }
if ( result instanceof Object === false ) { continue; } if ( result instanceof Object === false ) { continue; }
const content = result.content; const content = result.content;
let lastIndex = 0; const slices = µBlock.processDirectives.split(content);
for (;;) { for ( let i = 0, n = slices.length - 1; i < n; i++ ) {
if ( rootDirectoryURL === undefined ) { break; } const slice = content.slice(slices[i+0], slices[i+1]);
const match = reInclude.exec(content); if ( (i & 1) !== 0 ) {
if ( match === null ) { break; } out.push(slice);
if ( toParsedURL(match[1]) !== undefined ) { continue; } continue;
if ( match[1].indexOf('..') !== -1 ) { continue; } }
// Compute nested list path relative to parent list path let lastIndex = 0;
const pos = result.url.lastIndexOf('/'); for (;;) {
if ( pos === -1 ) { continue; } if ( rootDirectoryURL === undefined ) { break; }
const subURL = result.url.slice(0, pos + 1) + match[1]; const match = reInclude.exec(slice);
if ( sublistURLs.has(subURL) ) { continue; } if ( match === null ) { break; }
sublistURLs.add(subURL); if ( toParsedURL(match[1]) !== undefined ) { continue; }
out.push( if ( match[1].indexOf('..') !== -1 ) { continue; }
content.slice(lastIndex, match.index), // Compute nested list path relative to parent list path
`! >>>>>>>> ${subURL}`, const pos = result.url.lastIndexOf('/');
api.fetchText(subURL), if ( pos === -1 ) { continue; }
`! <<<<<<<< ${subURL}` const subURL = result.url.slice(0, pos + 1) + match[1];
); if ( sublistURLs.has(subURL) ) { continue; }
lastIndex = reInclude.lastIndex; sublistURLs.add(subURL);
out.push(
slice.slice(lastIndex, match.index),
`! >>>>>>>> ${subURL}`,
api.fetchText(subURL),
`! <<<<<<<< ${subURL}`
);
lastIndex = reInclude.lastIndex;
}
out.push(lastIndex === 0 ? slice : slice.slice(lastIndex));
} }
out.push(lastIndex === 0 ? content : content.slice(lastIndex));
} }
return out; return out;
}; };

View File

@ -799,7 +799,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// https://adblockplus.org/en/filters // https://adblockplus.org/en/filters
const staticNetFilteringEngine = this.staticNetFilteringEngine; const staticNetFilteringEngine = this.staticNetFilteringEngine;
const staticExtFilteringEngine = this.staticExtFilteringEngine; const staticExtFilteringEngine = this.staticExtFilteringEngine;
const lineIter = new this.LineIterator(this.processDirectives(rawText)); const lineIter = new this.LineIterator(this.processDirectives.prune(rawText));
const parser = new vAPI.StaticFilteringParser(); const parser = new vAPI.StaticFilteringParser();
parser.setMaxTokenLength(this.urlTokenizer.MAX_TOKEN_LENGTH); parser.setMaxTokenLength(this.urlTokenizer.MAX_TOKEN_LENGTH);
@ -854,69 +854,81 @@ self.addEventListener('hiddenSettingsChanged', ( ) => {
// https://github.com/AdguardTeam/AdguardBrowserExtension/issues/917 // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/917
µBlock.processDirectives = function(content) { µBlock.processDirectives = {
const reIf = /^!#(if|endif)\b([^\n]*)/gm; // This method returns an array of indices, corresponding to position in
const stack = []; // the content string which should alternatively be parsed and discarded.
const shouldDiscard = ( ) => stack.some(v => v); split: function(content) {
const parts = []; const reIf = /^!#(if|endif)\b([^\n]*)(?:[\n\r]+|$)/gm;
let beg = 0, discard = false; const stack = [];
const shouldDiscard = ( ) => stack.some(v => v);
const parts = [ 0 ];
let discard = false;
while ( beg < content.length ) { for (;;) {
const match = reIf.exec(content); const match = reIf.exec(content);
if ( match === null ) { break; } if ( match === null ) { break; }
switch ( match[1] ) { switch ( match[1] ) {
case 'if': case 'if':
let expr = match[2].trim(); let expr = match[2].trim();
const target = expr.charCodeAt(0) === 0x21 /* '!' */; const target = expr.charCodeAt(0) === 0x21 /* '!' */;
if ( target ) { expr = expr.slice(1); } if ( target ) { expr = expr.slice(1); }
const token = this.processDirectives.tokens.get(expr); const token = this.tokens.get(expr);
const startDiscard = const startDiscard =
token === 'false' && token === 'false' &&
target === false || target === false ||
token !== undefined && token !== undefined &&
vAPI.webextFlavor.soup.has(token) === target; vAPI.webextFlavor.soup.has(token) === target;
if ( discard === false && startDiscard ) { if ( discard === false && startDiscard ) {
parts.push(content.slice(beg, match.index)); parts.push(match.index);
discard = true; discard = true;
}
stack.push(startDiscard);
break;
case 'endif':
stack.pop();
const stopDiscard = shouldDiscard() === false;
if ( discard && stopDiscard ) {
parts.push(match.index + match[0].length);
discard = false;
}
break;
default:
break;
} }
stack.push(startDiscard);
break;
case 'endif':
stack.pop();
const stopDiscard = shouldDiscard() === false;
if ( discard && stopDiscard ) {
beg = match.index + match[0].length + 1;
discard = false;
}
break;
default:
break;
} }
}
if ( stack.length === 0 && parts.length !== 0 ) { parts.push(content.length);
parts.push(content.slice(beg)); return parts;
content = parts.join('\n'); },
}
return content.trim(); prune: function(content) {
const parts = this.split(content);
const out = [];
for ( let i = 0, n = parts.length - 1; i < n; i += 2 ) {
const beg = parts[i+0];
const end = parts[i+1];
out.push(content.slice(beg, end));
}
return out.join('\n');
},
tokens: new Map([
[ 'ext_ublock', 'ublock' ],
[ 'env_chromium', 'chromium' ],
[ 'env_edge', 'edge' ],
[ 'env_firefox', 'firefox' ],
[ 'env_legacy', 'legacy' ],
[ 'env_mobile', 'mobile' ],
[ 'env_safari', 'safari' ],
[ 'cap_html_filtering', 'html_filtering' ],
[ 'cap_user_stylesheet', 'user_stylesheet' ],
[ 'false', 'false' ],
]),
}; };
µBlock.processDirectives.tokens = new Map([
[ 'ext_ublock', 'ublock' ],
[ 'env_chromium', 'chromium' ],
[ 'env_edge', 'edge' ],
[ 'env_firefox', 'firefox' ],
[ 'env_legacy', 'legacy' ],
[ 'env_mobile', 'mobile' ],
[ 'env_safari', 'safari' ],
[ 'cap_html_filtering', 'html_filtering' ],
[ 'cap_user_stylesheet', 'user_stylesheet' ],
[ 'false', 'false' ],
]);
/******************************************************************************/ /******************************************************************************/
µBlock.loadRedirectResources = async function() { µBlock.loadRedirectResources = async function() {