uBO will fallback using a JSON string when trying to encode an array
buffer in Chromium version 59 and earlier.
This commit is contained in:
Raymond Hill 2019-03-16 09:00:31 -04:00
parent 7875bb6ebc
commit 008370e4b9
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 77 additions and 10 deletions

View File

@ -372,11 +372,13 @@ HNTrieContainer.prototype = {
},
unserialize: function(selfie, decoder) {
this.needle = '';
const shouldDecode = typeof selfie === 'string';
let byteLength = shouldDecode
? decoder.decodeSize(selfie)
: selfie.length << 2;
byteLength = byteLength + HNTRIE_PAGE_SIZE-1 & ~(HNTRIE_PAGE_SIZE-1);
if ( byteLength === 0 ) { return; }
if ( this.wasmMemory !== null ) {
const pageCountBefore = this.buf.length >>> 16;
const pageCountAfter = byteLength >>> 16;
@ -394,7 +396,6 @@ HNTrieContainer.prototype = {
} else {
this.buf32.set(selfie);
}
this.needle = '';
},
//--------------------------------------------------------------------------

View File

@ -935,17 +935,17 @@
// https://github.com/AdguardTeam/AdguardBrowserExtension/issues/917
µBlock.processDirectives = function(content) {
var reIf = /^!#(if|endif)\b([^\n]*)/gm,
parts = [],
beg = 0, depth = 0, discard = false;
const reIf = /^!#(if|endif)\b([^\n]*)/gm;
const parts = [];
let beg = 0, depth = 0, discard = false;
while ( beg < content.length ) {
var match = reIf.exec(content);
const match = reIf.exec(content);
if ( match === null ) { break; }
if ( match[1] === 'if' ) {
var expr = match[2].trim();
var target = expr.startsWith('!');
let expr = match[2].trim();
const target = expr.startsWith('!');
if ( target ) { expr = expr.slice(1); }
var token = this.processDirectives.tokens.get(expr);
const token = this.processDirectives.tokens.get(expr);
if (
depth === 0 &&
discard === false &&
@ -1034,8 +1034,11 @@
'compiled/' + this.pslAssetKey
).then(details =>
publicSuffixList.fromSelfie(details.content, µBlock.base128)
).then(valid => {
if ( valid === true ) { return; }
).catch(reason => {
console.info(reason);
return false;
}).then(success => {
if ( success ) { return; }
return this.assets.get(this.pslAssetKey, details => {
if ( details.content !== '' ) {
this.compilePublicSuffixList(details.content);

View File

@ -505,9 +505,22 @@
// Could expand the LZ4 codec API to be able to return UTF8-safe string
// representation of a compressed buffer, and thus the code below could be
// moved LZ4 codec-side.
// https://github.com/uBlockOrigin/uBlock-issues/issues/461
// Provide a fallback encoding for Chromium 59 and less by issuing a plain
// JSON string. The fallback can be removed once min supported version is
// above 59.
µBlock.base128 = {
encode: function(arrbuf, arrlen) {
if (
vAPI.webextFlavor.soup.has('chromium') &&
vAPI.webextFlavor.major < 60
) {
return this.encodeJSON(arrbuf);
}
return this.encodeBase128(arrbuf, arrlen);
},
encodeBase128: function(arrbuf, arrlen) {
const inbuf = new Uint8Array(arrbuf, 0, arrlen);
const inputLength = arrlen;
let _7cnt = Math.floor(inputLength / 7);
@ -556,6 +569,9 @@
const textDecoder = new TextDecoder();
return textDecoder.decode(outbuf);
},
encodeJSON: function(arrbuf) {
return JSON.stringify(Array.from(new Uint32Array(arrbuf)));
},
// TODO:
// Surprisingly, there does not seem to be any performance gain when
// first converting the input string into a Uint8Array through
@ -568,6 +584,22 @@
// const inbuf = textEncoder.encode(instr);
// const inputLength = inbuf.byteLength;
decode: function(instr, arrbuf) {
if ( instr.length === 0 ) { return; }
if ( instr.charCodeAt(0) === 0x5B /* '[' */ ) {
const outbuf = this.decodeJSON(instr, arrbuf);
if ( outbuf !== undefined ) {
return outbuf;
}
}
if (
vAPI.webextFlavor.soup.has('chromium') &&
vAPI.webextFlavor.major < 60
) {
throw new Error('Unexpected µBlock.base128 encoding');
}
return this.decodeBase128(instr, arrbuf);
},
decodeBase128: function(instr, arrbuf) {
const inputLength = instr.length;
let _8cnt = inputLength >>> 3;
let outputLength = _8cnt * 7;
@ -599,7 +631,37 @@
}
return outbuf;
},
decodeJSON: function(instr, arrbuf) {
let buf;
try {
buf = JSON.parse(instr);
} catch (ex) {
}
if ( Array.isArray(buf) === false ) { return; }
const outbuf = arrbuf instanceof ArrayBuffer === false
? new Uint32Array(buf.length << 2)
: new Uint32Array(arrbuf);
outbuf.set(buf);
return new Uint8Array(outbuf.buffer);
},
decodeSize: function(instr) {
if ( instr.length === 0 ) { return 0; }
if ( instr.charCodeAt(0) === 0x5B /* '[' */ ) {
let buf;
try {
buf = JSON.parse(instr);
} catch (ex) {
}
if ( Array.isArray(buf) ) {
return buf.length << 2;
}
}
if (
vAPI.webextFlavor.soup.has('chromium') &&
vAPI.webextFlavor.major < 60
) {
throw new Error('Unexpected µBlock.base128 encoding');
}
const size = (instr.length >>> 3) * 7;
const rem = instr.length & 7;
return rem === 0 ? size : size + rem - 1;

View File

@ -500,6 +500,7 @@ const fromSelfie = function(selfie, decoder) {
}
const bufferStr = selfie.slice(pos + 1);
byteLength = decoder.decodeSize(bufferStr);
if ( byteLength === 0 ) { return false; }
allocateBuffers(byteLength);
decoder.decode(bufferStr, pslBuffer8.buffer);
} else if (