Closed Procyon-b closed 4 years ago
Completely irrelevant word such as xyz
also works as the third parameter.
The scriptlet works fine.
It's a browser quirk: when you assign a getter to onselectstart
, it appears Chromium bypasses the getter when it wants to internally fire the onselectstart
event (and probably any on...
event), and since no valid function is assign to onselectstart
, the event is left unhandled.
OK, I get it now. This is problem I encountered when programming a sandbox for an extension.
Chrome doesn't like this way of setting a property. It doesn't work. You have to make a copy of the original 'getter' and 'setter' and call them to get/set a value.
Here is a proof of concept (but with the OldGetter
OldSetter
properties public).
Tested in chrome and FF.
also available here for a short time: http://users.skynet.be/alternity/ubo-res-b.js
test with users.skynet.be##+js(myacis, document.onselectstart, /ftrue/)' and 'users.skynet.be##+js(myacis, document.onselectstart, /ssdftrue/)
/// my-abort-current-inline-script.js
/// alias myacis.js
(function() {
const target = '{{1}}';
if ( target === '' || target === '{{1}}' ) { return; }
const needle = '{{2}}';
let reText = '.?';
if ( needle !== '' && needle !== '{{2}}' ) {
reText = /^\/.+\/$/.test(needle)
? needle.slice(1,-1)
: needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const thisScript = document.currentScript;
const re = new RegExp(reText);
const chain = target.split('.');
let owner = window;
let prop;
for (;;) {
prop = chain.shift();
if ( chain.length === 0 ) { break; }
owner = owner[prop];
if ( owner instanceof Object === false ) { return; }
}
let value;
let desc = Object.getOwnPropertyDescriptor(owner, prop);
if (
desc instanceof Object === false ||
desc.get instanceof Function === false
) {
value = owner[prop];
desc = undefined;
}
const magic = String.fromCharCode(Date.now() % 26 + 97) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
const validate = function() {
const e = document.currentScript;
if (
e instanceof HTMLScriptElement &&
e.src === '' &&
e !== thisScript &&
re.test(e.textContent)
) {
throw new ReferenceError(magic);
}
};
owner.OldSetter=owner.__lookupSetter__(prop);
owner.OldGetter=owner.__lookupGetter__(prop);
Object.defineProperty(owner, prop, {
get: function() {
validate();
return this.OldGetter();
},
set: function(a) {
validate();
this.OldSetter(a);
}
});
const oe = window.onerror;
window.onerror = function(msg) {
if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
return true;
}
if ( oe instanceof Function ) {
return oe.apply(this, arguments);
}
}.bind();
})();
Obviously, this version of the code is specific to this test. Multiple calls to 'acis' on 'document' will overwrite backed-up getter and setter.
__lookupSetter__
is:
Deprecated This feature is no longer recommended.
At this point, I don't see a real world issue, the provided case is to prevent the page from disabling onselectstart
and oncontextmenu
, which can be accomplished with users.skynet.be##+js(set, document.onselectstart, null)
etc.
It is deprecated for many years, but I haven't found a way to achieve the same effect (setting a value from a inside a new setter).
This is only a test case. What if filtering is needed on the string (in another case)? Scripts on a page makes multiple attempts to read a value, but we only need it to fail at one place. (or maybe it's multiple versions of the page) This case must exist, or else there is no need of a third parameter in acis.
And is acis the only resource that uses this string matching?
Edit I'll try to find another method.
or else there is no need of a third parameter in acis.
This is your argument? Because of cases involving one set of properties we should sacrifice filtering on text segment for all other cases where it's currently working fine?
I don't say that we should sacrifice anything. Your argument about __lookupSetter__
is completely valid, And I wouldn't want acis to be changed considering that.
The third parameter is working fine for other properties such as document.write
. (Test case I used [NSFW]: russianbeauties.jp
The third parameter is vital here.)
@Yuki2718 indeed it works (did my own test too). When testing, I thought the problem was more wide than it is actually. chrome is soooooo weird.
At this point, I don't see a real world issue
Here it is, another case - an user has reported a Disqus comment section breakage, due to an acis
filter which shouldn't even run because none of inline scripts at notalwaysright.com
contain "admiral" text anymore: https://github.com/uBlockOrigin/uAssets/issues/17039#issuecomment-1454900669.
And even if we travel back in time where "admiral" was still present, most likely the filter was still aborting too many inline scripts, because the page contains several different inline scripts with document.createElement
property.
Anyway, on the other side, it doesn't seem to be aborting all inline scripts which contains document.createElement
property, because if add:
notalwaysright.com#@#+js(acis, document.createElement, admiral)
notalwaysright.com##+js(acis, document.createElement)
it breaks all the inline scripts with document.createElement
which causes the whole page become much more broken, notalwaysright.com##+js(acis, document.createElement, admiral)
which breaks only Disqus comment section for random users.notalwaysright.com##+js(acis, document.createElement, admiral)
is not perfectly equal to
notalwaysright.com##+js(acis, document.createElement)
,
because not all instances of document.createElement
are aborted.notalwaysright.com##+js(acis, document.createElement, admiral)
might depend on different (random) factors for different users,
that would explain why some users get the Disqus comment section breakage
and some other users were unable to reproduceThere is 118 ##+js(acis/acs, document.createElement, [value])
filters in uBlock filters, most likely some of the websites have breakages.
Prerequisites
Description
A while ago I've noticed a problem with a specific type of cosmetic/js filter. I didn't mind since the browser I was using on that computer is an older version of chrome (70). But today I took the time to test on several different browsers and computers.
The problem is with
https://github.com/gorhill/uBlock/wiki/Resources-Library#acisjs-
When specifying a third parameter (a string or a RE), this parameter must be matched for the filter to be applied. It works as documented with FF & WF, but not in any version of chrome. In chrome it always matches successfully whatever the string.A specific URL where the issue occurs
http://users.skynet.be/x-or/
Steps to Reproduce
document.onselectstart =
users.skynet.be##+js(acis, document.onselectstart, /ftrue/)
Reload the page and select text. It worksusers.skynet.be##+js(acis, document.onselectstart, /ssfsdfsftrue/)
Reload and try selecting text. It shouldn't work (OK in FF & WF), but in chrome you can select text.Expected behavior:
A non-matching string should ignore the filter.
Actual behavior:
In chrome it always matches whatever the string.
Your environment