Improve various scriptlets

Specifically, improve proxying of native methods.
This commit is contained in:
Raymond Hill 2024-08-16 11:49:16 -04:00
parent 9ced01ebf7
commit 56dfdd2568
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 127 additions and 143 deletions

View File

@ -1446,9 +1446,6 @@ function replaceFetchResponseFn(
builtinScriptlets.push({ builtinScriptlets.push({
name: 'proxy-apply.fn', name: 'proxy-apply.fn',
fn: proxyApplyFn, fn: proxyApplyFn,
dependencies: [
'safe-self.fn',
],
}); });
function proxyApplyFn( function proxyApplyFn(
target = '', target = '',
@ -1465,12 +1462,28 @@ function proxyApplyFn(
} }
const fn = context[prop]; const fn = context[prop];
if ( typeof fn !== 'function' ) { return; } if ( typeof fn !== 'function' ) { return; }
const fnname = fn.name;
const toString = (function toString() {
return `function ${fnname}() { [native code] }`;
}).bind(null);
if ( fn.prototype && fn.prototype.constructor === fn ) { if ( fn.prototype && fn.prototype.constructor === fn ) {
context[prop] = new Proxy(fn, { construct: handler }); context[prop] = new Proxy(fn, {
return (...args) => { return Reflect.construct(...args); }; construct: handler,
get(target, prop, receiver) {
if ( prop === 'toString' ) { return toString; }
return Reflect.get(target, prop, receiver);
},
});
return (...args) => Reflect.construct(...args);
} }
context[prop] = new Proxy(fn, { apply: handler }); context[prop] = new Proxy(fn, {
return (...args) => { return Reflect.apply(...args); }; apply: handler,
get(target, prop, receiver) {
if ( prop === 'toString' ) { return toString; }
return Reflect.get(target, prop, receiver);
},
});
return (...args) => Reflect.apply(...args);
} }
/******************************************************************************* /*******************************************************************************
@ -1676,6 +1689,7 @@ builtinScriptlets.push({
], ],
fn: addEventListenerDefuser, fn: addEventListenerDefuser,
dependencies: [ dependencies: [
'proxy-apply.fn',
'run-at.fn', 'run-at.fn',
'safe-self.fn', 'safe-self.fn',
'should-debug.fn', 'should-debug.fn',
@ -1732,9 +1746,8 @@ function addEventListenerDefuser(
} }
return matchesBoth; return matchesBoth;
}; };
const trapEddEventListeners = ( ) => { runAt(( ) => {
const eventListenerHandler = { proxyApplyFn('EventTarget.prototype.addEventListener', function(target, thisArg, args) {
apply: function(target, thisArg, args) {
let t, h; let t, h;
try { try {
t = String(args[0]); t = String(args[0]);
@ -1755,21 +1768,7 @@ function addEventListenerDefuser(
return safe.uboLog(logPrefix, `Prevented: ${t}\n${h}\n${elementDetails(thisArg)}`); return safe.uboLog(logPrefix, `Prevented: ${t}\n${h}\n${elementDetails(thisArg)}`);
} }
return Reflect.apply(target, thisArg, args); return Reflect.apply(target, thisArg, args);
}, });
get(target, prop, receiver) {
if ( prop === 'toString' ) {
return target.toString.bind(target);
}
return Reflect.get(target, prop, receiver);
},
};
self.EventTarget.prototype.addEventListener = new Proxy(
self.EventTarget.prototype.addEventListener,
eventListenerHandler
);
};
runAt(( ) => {
trapEddEventListeners();
}, extraArgs.runAt); }, extraArgs.runAt);
} }
@ -2475,6 +2474,7 @@ builtinScriptlets.push({
], ],
fn: noSetIntervalIf, fn: noSetIntervalIf,
dependencies: [ dependencies: [
'proxy-apply.fn',
'safe-self.fn', 'safe-self.fn',
], ],
}); });
@ -2495,8 +2495,7 @@ function noSetIntervalIf(
delay = parseInt(delay, 10); delay = parseInt(delay, 10);
} }
const reNeedle = safe.patternToRegex(needle); const reNeedle = safe.patternToRegex(needle);
self.setInterval = new Proxy(self.setInterval, { proxyApplyFn('setInterval', function setInterval(target, thisArg, args) {
apply: function(target, thisArg, args) {
const a = args[0] instanceof Function const a = args[0] instanceof Function
? String(safe.Function_toString(args[0])) ? String(safe.Function_toString(args[0]))
: String(args[0]); : String(args[0]);
@ -2517,13 +2516,6 @@ function noSetIntervalIf(
safe.uboLog(logPrefix, `Prevented:\n${a}\n${b}`); safe.uboLog(logPrefix, `Prevented:\n${a}\n${b}`);
} }
return Reflect.apply(target, thisArg, args); return Reflect.apply(target, thisArg, args);
},
get(target, prop, receiver) {
if ( prop === 'toString' ) {
return target.toString.bind(target);
}
return Reflect.get(target, prop, receiver);
},
}); });
} }
@ -2538,6 +2530,7 @@ builtinScriptlets.push({
], ],
fn: noSetTimeoutIf, fn: noSetTimeoutIf,
dependencies: [ dependencies: [
'proxy-apply.fn',
'safe-self.fn', 'safe-self.fn',
], ],
}); });
@ -2558,8 +2551,7 @@ function noSetTimeoutIf(
delay = parseInt(delay, 10); delay = parseInt(delay, 10);
} }
const reNeedle = safe.patternToRegex(needle); const reNeedle = safe.patternToRegex(needle);
self.setTimeout = new Proxy(self.setTimeout, { proxyApplyFn('setTimeout', function setTimeout(target, thisArg, args) {
apply: function(target, thisArg, args) {
const a = args[0] instanceof Function const a = args[0] instanceof Function
? String(safe.Function_toString(args[0])) ? String(safe.Function_toString(args[0]))
: String(args[0]); : String(args[0]);
@ -2580,13 +2572,6 @@ function noSetTimeoutIf(
safe.uboLog(logPrefix, `Prevented:\n${a}\n${b}`); safe.uboLog(logPrefix, `Prevented:\n${a}\n${b}`);
} }
return Reflect.apply(target, thisArg, args); return Reflect.apply(target, thisArg, args);
},
get(target, prop, receiver) {
if ( prop === 'toString' ) {
return target.toString.bind(target);
}
return Reflect.get(target, prop, receiver);
},
}); });
} }
@ -2815,6 +2800,7 @@ builtinScriptlets.push({
], ],
fn: noWindowOpenIf, fn: noWindowOpenIf,
dependencies: [ dependencies: [
'proxy-apply.fn',
'safe-self.fn', 'safe-self.fn',
], ],
}); });
@ -2845,8 +2831,7 @@ function noWindowOpenIf(
setTimeout(( ) => { decoyElem.remove(); }, autoRemoveAfter * 1000); setTimeout(( ) => { decoyElem.remove(); }, autoRemoveAfter * 1000);
return decoyElem; return decoyElem;
}; };
window.open = new Proxy(window.open, { proxyApplyFn('open', function open(target, thisArg, args) {
apply: function(target, thisArg, args) {
const haystack = args.join(' '); const haystack = args.join(' ');
if ( rePattern.test(haystack) !== targetMatchResult ) { if ( rePattern.test(haystack) !== targetMatchResult ) {
if ( safe.logLevel > 1 ) { if ( safe.logLevel > 1 ) {
@ -2863,7 +2848,7 @@ function noWindowOpenIf(
if ( typeof popup === 'object' && popup !== null ) { if ( typeof popup === 'object' && popup !== null ) {
Object.defineProperty(popup, 'closed', { value: false }); Object.defineProperty(popup, 'closed', { value: false });
} else { } else {
const noopFunc = (function(){}).bind(self); const noopFunc = function open(){};
popup = new Proxy(self, { popup = new Proxy(self, {
get: function(target, prop) { get: function(target, prop) {
if ( prop === 'closed' ) { return false; } if ( prop === 'closed' ) { return false; }
@ -2889,7 +2874,6 @@ function noWindowOpenIf(
}); });
} }
return popup; return popup;
}
}); });
} }