mirror of
https://github.com/gorhill/uBlock.git
synced 2025-02-01 04:31:36 +01:00
Improve trusted-replace-argument
scriptlet
As discussed with filter list maintainers.
This commit is contained in:
parent
36db7f8327
commit
3417fe3d5d
@ -229,7 +229,7 @@ export function removeAttr(
|
||||
if ( rawToken === '' ) { return; }
|
||||
const safe = safeSelf();
|
||||
const logPrefix = safe.makeLogPrefix('remove-attr', rawToken, rawSelector, behavior);
|
||||
const tokens = rawToken.split(/\s*\|\s*/);
|
||||
const tokens = safe.String_split.call(rawToken, /\s*\|\s*/);
|
||||
const selector = tokens
|
||||
.map(a => `${rawSelector}[${CSS.escape(a)}]`)
|
||||
.join(',');
|
||||
@ -289,7 +289,7 @@ export function removeAttr(
|
||||
subtree: true,
|
||||
});
|
||||
};
|
||||
runAt(( ) => { start(); }, behavior.split(/\s+/));
|
||||
runAt(( ) => { start(); }, safe.String_split.call(behavior, /\s+/));
|
||||
}
|
||||
registerScriptlet(removeAttr, {
|
||||
name: 'remove-attr.js',
|
||||
|
@ -53,7 +53,8 @@ registerScriptlet(getSafeCookieValuesFn, {
|
||||
/******************************************************************************/
|
||||
|
||||
export function getAllCookiesFn() {
|
||||
return document.cookie.split(/\s*;\s*/).map(s => {
|
||||
const safe = safeSelf();
|
||||
return safe.String_split.call(document.cookie, /\s*;\s*/).map(s => {
|
||||
const pos = s.indexOf('=');
|
||||
if ( pos === 0 ) { return; }
|
||||
if ( pos === -1 ) { return `${s.trim()}=`; }
|
||||
@ -64,6 +65,9 @@ export function getAllCookiesFn() {
|
||||
}
|
||||
registerScriptlet(getAllCookiesFn, {
|
||||
name: 'get-all-cookies.fn',
|
||||
dependencies: [
|
||||
safeSelf,
|
||||
],
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
@ -71,7 +75,8 @@ registerScriptlet(getAllCookiesFn, {
|
||||
export function getCookieFn(
|
||||
name = ''
|
||||
) {
|
||||
for ( const s of document.cookie.split(/\s*;\s*/) ) {
|
||||
const safe = safeSelf();
|
||||
for ( const s of safe.String_split.call(document.cookie, /\s*;\s*/) ) {
|
||||
const pos = s.indexOf('=');
|
||||
if ( pos === -1 ) { continue; }
|
||||
if ( s.slice(0, pos) !== name ) { continue; }
|
||||
@ -80,6 +85,9 @@ export function getCookieFn(
|
||||
}
|
||||
registerScriptlet(getCookieFn, {
|
||||
name: 'get-cookie.fn',
|
||||
dependencies: [
|
||||
safeSelf,
|
||||
],
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
@ -349,7 +357,7 @@ export function removeCookie(
|
||||
}, ms);
|
||||
};
|
||||
const remove = ( ) => {
|
||||
document.cookie.split(';').forEach(cookieStr => {
|
||||
safe.String_split.call(document.cookie, ';').forEach(cookieStr => {
|
||||
const pos = cookieStr.indexOf('=');
|
||||
if ( pos === -1 ) { return; }
|
||||
const cookieName = cookieStr.slice(0, pos).trim();
|
||||
@ -387,7 +395,7 @@ export function removeCookie(
|
||||
window.addEventListener('beforeunload', remove);
|
||||
if ( typeof extraArgs.when !== 'string' ) { return; }
|
||||
const supportedEventTypes = [ 'scroll', 'keydown' ];
|
||||
const eventTypes = extraArgs.when.split(/\s/);
|
||||
const eventTypes = safe.String_split.call(extraArgs.when, /\s/);
|
||||
for ( const type of eventTypes ) {
|
||||
if ( supportedEventTypes.includes(type) === false ) { continue; }
|
||||
document.addEventListener(type, ( ) => {
|
||||
|
@ -52,7 +52,7 @@ export function proxyApplyFn(
|
||||
}
|
||||
reflect() {
|
||||
const r = Reflect.construct(this.callFn, this.callArgs);
|
||||
this.callFn = this.callArgs = undefined;
|
||||
this.callFn = this.callArgs = this.private = undefined;
|
||||
proxyApplyFn.ctorContexts.push(this);
|
||||
return r;
|
||||
}
|
||||
@ -75,7 +75,7 @@ export function proxyApplyFn(
|
||||
}
|
||||
reflect() {
|
||||
const r = Reflect.apply(this.callFn, this.thisArg, this.callArgs);
|
||||
this.callFn = this.thisArg = this.callArgs = undefined;
|
||||
this.callFn = this.thisArg = this.callArgs = this.private = undefined;
|
||||
proxyApplyFn.applyContexts.push(this);
|
||||
return r;
|
||||
}
|
||||
|
@ -71,25 +71,39 @@ export function trustedReplaceArgument(
|
||||
const reCondition = extraArgs.condition
|
||||
? safe.patternToRegex(extraArgs.condition)
|
||||
: /^/;
|
||||
proxyApplyFn(propChain, function(context) {
|
||||
const getArg = context => {
|
||||
if ( argposRaw === 'this' ) { return context.thisArg; }
|
||||
const { callArgs } = context;
|
||||
if ( argposRaw === '' ) {
|
||||
safe.uboLog(logPrefix, `Arguments:\n${callArgs.join('\n')}`);
|
||||
return context.reflect();
|
||||
}
|
||||
const argpos = argoffset >= 0 ? argoffset : callArgs.length - argoffset;
|
||||
if ( argpos < 0 || argpos >= callArgs.length ) {
|
||||
if ( argpos < 0 || argpos >= callArgs.length ) { return; }
|
||||
context.private = { argpos };
|
||||
return callArgs[argpos];
|
||||
};
|
||||
const setArg = (context, value) => {
|
||||
if ( argposRaw === 'this' ) {
|
||||
if ( value !== context.thisArg ) {
|
||||
context.thisArg = value;
|
||||
}
|
||||
} else if ( context.private ) {
|
||||
context.callArgs[context.private.argpos] = value;
|
||||
}
|
||||
};
|
||||
proxyApplyFn(propChain, function(context) {
|
||||
if ( argposRaw === '' ) {
|
||||
safe.uboLog(logPrefix, `Arguments:\n${context.callArgs.join('\n')}`);
|
||||
return context.reflect();
|
||||
}
|
||||
const argBefore = callArgs[argpos];
|
||||
const argBefore = getArg(context);
|
||||
if ( safe.RegExp_test.call(reCondition, argBefore) === false ) {
|
||||
return context.reflect();
|
||||
}
|
||||
const argAfter = replacer && typeof argBefore === 'string'
|
||||
? argBefore.replace(replacer.re, replacer.replacement)
|
||||
: value;
|
||||
callArgs[argpos] = argAfter;
|
||||
safe.uboLog(logPrefix, `Replaced argument:\nBefore: ${JSON.stringify(argBefore)}\nAfter: ${argAfter}`);
|
||||
if ( argAfter !== argBefore ) {
|
||||
setArg(context, argAfter);
|
||||
safe.uboLog(logPrefix, `Replaced argument:\nBefore: ${JSON.stringify(argBefore)}\nAfter: ${argAfter}`);
|
||||
}
|
||||
return context.reflect();
|
||||
});
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ export function safeSelf() {
|
||||
'RegExp_exec': self.RegExp.prototype.exec,
|
||||
'Request_clone': self.Request.prototype.clone,
|
||||
'String_fromCharCode': String.fromCharCode,
|
||||
'String_split': String.prototype.split,
|
||||
'XMLHttpRequest': self.XMLHttpRequest,
|
||||
'addEventListener': self.EventTarget.prototype.addEventListener,
|
||||
'removeEventListener': self.EventTarget.prototype.removeEventListener,
|
||||
|
@ -192,7 +192,7 @@ function abortCurrentScriptCore(
|
||||
const reContext = safe.patternToRegex(context);
|
||||
const extraArgs = safe.getExtraArgs(Array.from(arguments), 3);
|
||||
const thisScript = document.currentScript;
|
||||
const chain = target.split('.');
|
||||
const chain = safe.String_split.call(target, '.');
|
||||
let owner = window;
|
||||
let prop;
|
||||
for (;;) {
|
||||
@ -406,6 +406,7 @@ builtinScriptlets.push({
|
||||
dependencies: [
|
||||
'matches-stack-trace.fn',
|
||||
'object-find-owner.fn',
|
||||
'safe-self.fn',
|
||||
],
|
||||
});
|
||||
// When no "prune paths" argument is provided, the scriptlet is
|
||||
@ -422,11 +423,12 @@ function objectPruneFn(
|
||||
extraArgs = {}
|
||||
) {
|
||||
if ( typeof rawPrunePaths !== 'string' ) { return; }
|
||||
const safe = safeSelf();
|
||||
const prunePaths = rawPrunePaths !== ''
|
||||
? rawPrunePaths.split(/ +/)
|
||||
? safe.String_split.call(rawPrunePaths, / +/)
|
||||
: [];
|
||||
const needlePaths = prunePaths.length !== 0 && rawNeedlePaths !== ''
|
||||
? rawNeedlePaths.split(/ +/)
|
||||
? safe.String_split.call(rawNeedlePaths, / +/)
|
||||
: [];
|
||||
if ( stackNeedleDetails.matchAll !== true ) {
|
||||
if ( matchesStackTrace(stackNeedleDetails, extraArgs.logstack) === false ) {
|
||||
@ -547,7 +549,7 @@ function matchesStackTrace(
|
||||
// Normalize stack trace
|
||||
const reLine = /(.*?@)?(\S+)(:\d+):\d+\)?$/;
|
||||
const lines = [];
|
||||
for ( let line of error.stack.split(/[\n\r]+/) ) {
|
||||
for ( let line of safe.String_split.call(error.stack, /[\n\r]+/) ) {
|
||||
if ( line.includes(exceptionToken) ) { continue; }
|
||||
line = line.trim();
|
||||
const match = safe.RegExp_exec.call(reLine, line);
|
||||
@ -594,8 +596,8 @@ function parsePropertiesToMatch(propsToMatch, implicit = '') {
|
||||
const needles = new Map();
|
||||
if ( propsToMatch === undefined || propsToMatch === '' ) { return needles; }
|
||||
const options = { canNegate: true };
|
||||
for ( const needle of propsToMatch.split(/\s+/) ) {
|
||||
const [ prop, pattern ] = needle.split(':');
|
||||
for ( const needle of safe.String_split.call(propsToMatch, /\s+/) ) {
|
||||
const [ prop, pattern ] = safe.String_split.call(needle, ':');
|
||||
if ( prop === '' ) { continue; }
|
||||
if ( pattern !== undefined ) {
|
||||
needles.set(prop, safe.initPattern(pattern, options));
|
||||
@ -1643,7 +1645,7 @@ function noFetchIf(
|
||||
const safe = safeSelf();
|
||||
const logPrefix = safe.makeLogPrefix('prevent-fetch', propsToMatch, responseBody, responseType);
|
||||
const needles = [];
|
||||
for ( const condition of propsToMatch.split(/\s+/) ) {
|
||||
for ( const condition of safe.String_split.call(propsToMatch, /\s+/) ) {
|
||||
if ( condition === '' ) { continue; }
|
||||
const pos = condition.indexOf(':');
|
||||
let key, value;
|
||||
@ -1797,7 +1799,7 @@ function removeClass(
|
||||
if ( rawToken === '' ) { return; }
|
||||
const safe = safeSelf();
|
||||
const logPrefix = safe.makeLogPrefix('remove-class', rawToken, rawSelector, behavior);
|
||||
const tokens = rawToken.split(/\s*\|\s*/);
|
||||
const tokens = safe.String_split.call(rawToken, /\s*\|\s*/);
|
||||
const selector = tokens
|
||||
.map(a => `${rawSelector}.${CSS.escape(a)}`)
|
||||
.join(',');
|
||||
@ -2510,12 +2512,12 @@ function m3uPrune(
|
||||
}
|
||||
text = before.trim() + '\n' + after.trim();
|
||||
reM3u.lastIndex = before.length + 1;
|
||||
toLog.push('Discarding', ...discard.split(/\n+/).map(s => `\t${s}`));
|
||||
toLog.push('Discarding', ...safe.String_split.call(discard, /\n+/).map(s => `\t${s}`));
|
||||
if ( reM3u.global === false ) { break; }
|
||||
}
|
||||
return text;
|
||||
}
|
||||
const lines = text.split(/\n\r|\n|\r/);
|
||||
const lines = safe.String_split.call(text, /\n\r|\n|\r/);
|
||||
for ( let i = 0; i < lines.length; i++ ) {
|
||||
if ( lines[i] === undefined ) { continue; }
|
||||
if ( pruneSpliceoutBlock(lines, i) ) { continue; }
|
||||
@ -2758,13 +2760,17 @@ function hrefSanitizer(
|
||||
builtinScriptlets.push({
|
||||
name: 'call-nothrow.js',
|
||||
fn: callNothrow,
|
||||
dependencies: [
|
||||
'safe-self.fn',
|
||||
],
|
||||
});
|
||||
function callNothrow(
|
||||
chain = ''
|
||||
) {
|
||||
if ( typeof chain !== 'string' ) { return; }
|
||||
if ( chain === '' ) { return; }
|
||||
const parts = chain.split('.');
|
||||
const safe = safeSelf();
|
||||
const parts = safe.String_split.call(chain, '.');
|
||||
let owner = window, prop;
|
||||
for (;;) {
|
||||
prop = parts.shift();
|
||||
@ -3095,7 +3101,7 @@ function trustedClickElement(
|
||||
const logPrefix = safe.makeLogPrefix('trusted-click-element', selectors, extraMatch, delay);
|
||||
|
||||
if ( extraMatch !== '' ) {
|
||||
const assertions = extraMatch.split(',').map(s => {
|
||||
const assertions = safe.String_split.call(extraMatch, ',').map(s => {
|
||||
const pos1 = s.indexOf(':');
|
||||
const s1 = pos1 !== -1 ? s.slice(0, pos1) : s;
|
||||
const not = s1.startsWith('!');
|
||||
@ -3163,7 +3169,7 @@ function trustedClickElement(
|
||||
return shadowRoot && querySelectorEx(inside, shadowRoot);
|
||||
};
|
||||
|
||||
const selectorList = selectors.split(/\s*,\s*/)
|
||||
const selectorList = safe.String_split.call(selectors, /\s*,\s*/)
|
||||
.filter(s => {
|
||||
try {
|
||||
void querySelectorEx(s);
|
||||
@ -3290,10 +3296,10 @@ function trustedPruneInboundObject(
|
||||
const extraArgs = safe.getExtraArgs(Array.from(arguments), 4);
|
||||
const needlePaths = [];
|
||||
if ( rawPrunePaths !== '' ) {
|
||||
needlePaths.push(...rawPrunePaths.split(/ +/));
|
||||
needlePaths.push(...safe.String_split.call(rawPrunePaths, / +/));
|
||||
}
|
||||
if ( rawNeedlePaths !== '' ) {
|
||||
needlePaths.push(...rawNeedlePaths.split(/ +/));
|
||||
needlePaths.push(...safe.String_split.call(rawNeedlePaths, / +/));
|
||||
}
|
||||
const stackNeedle = safe.initPattern(extraArgs.stackToMatch || '', { canNegate: true });
|
||||
const mustProcess = root => {
|
||||
@ -3455,7 +3461,7 @@ function trustedSuppressNativeMethod(
|
||||
if ( stack !== '' ) { return; }
|
||||
const safe = safeSelf();
|
||||
const logPrefix = safe.makeLogPrefix('trusted-suppress-native-method', methodPath, signature, how);
|
||||
const signatureArgs = signature.split(/\s*\|\s*/).map(v => {
|
||||
const signatureArgs = safe.String_split.call(signature, /\s*\|\s*/).map(v => {
|
||||
if ( /^".*"$/.test(v) ) {
|
||||
return { type: 'pattern', re: safe.patternToRegex(v.slice(1, -1)) };
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ export function validateConstantFn(trusted, raw, extraArgs = {}) {
|
||||
} else if ( raw.startsWith('{') && raw.endsWith('}') ) {
|
||||
try { value = safe.JSON_parse(raw).value; } catch(ex) { return; }
|
||||
}
|
||||
return raw;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user