Skip to content

Commit

Permalink
Fix potential corruption when reading serialized data
Browse files Browse the repository at this point in the history
Corrpution would occur when reading back serialized data which
contained multiple references to same instance of an object.

The issue could manifest when reading cache storage-related
data from the browser storage API, since the serializer is not
used when reading from indexedDB. Private/incognito mode
fall back on using browser storage API as cache storage.

Off the top of my head, I think the following conditions all
together could result in high likelihood of malfunction caused
by improperly deserializing data at launch time:

- Load from a selfie
- Selfie created after uBO ran for a while
- Selfie loaded from browser storage API (not the case by
  default)

Possibly related to reports of uBO malfunctioning:
uBlockOrigin/uBlock-issues#3217 (comment)
  • Loading branch information
gorhill committed May 3, 2024
1 parent e891465 commit c098eb8
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions src/js/s14e-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@ const _deserialize = ( ) => {
}
case I_OBJECT_SMALL:
case I_OBJECT_LARGE: {
const out = {};
readRefs.set(refCounter++, out);
const entries = [];
const size = type === I_OBJECT_SMALL
? charCodeToInt[readStr.charCodeAt(readPtr++)]
Expand All @@ -756,48 +758,45 @@ const _deserialize = ( ) => {
const v = _deserialize();
entries.push([ k, v ]);
}
const out = Object.fromEntries(entries);
readRefs.set(refCounter++, out);
Object.assign(out, Object.fromEntries(entries));
return out;
}
case I_ARRAY_SMALL:
case I_ARRAY_LARGE: {
const out = [];
readRefs.set(refCounter++, out);
const size = type === I_ARRAY_SMALL
? charCodeToInt[readStr.charCodeAt(readPtr++)]
: deserializeLargeUint();
for ( let i = 0; i < size; i++ ) {
out.push(_deserialize());
}
readRefs.set(refCounter++, out);
return out;
}
case I_SET_SMALL:
case I_SET_LARGE: {
const entries = [];
const out = new Set();
readRefs.set(refCounter++, out);
const size = type === I_SET_SMALL
? charCodeToInt[readStr.charCodeAt(readPtr++)]
: deserializeLargeUint();
for ( let i = 0; i < size; i++ ) {
entries.push(_deserialize());
out.add(_deserialize());
}
const out = new Set(entries);
readRefs.set(refCounter++, out);
return out;
}
case I_MAP_SMALL:
case I_MAP_LARGE: {
const entries = [];
const out = new Map();
readRefs.set(refCounter++, out);
const size = type === I_MAP_SMALL
? charCodeToInt[readStr.charCodeAt(readPtr++)]
: deserializeLargeUint();
for ( let i = 0; i < size; i++ ) {
const k = _deserialize();
const v = _deserialize();
entries.push([ k, v ]);
out.set(k, v);
}
const out = new Map(entries);
readRefs.set(refCounter++, out);
return out;
}
case I_ARRAYBUFFER: {
Expand Down

0 comments on commit c098eb8

Please sign in to comment.