LibWeb: Initialize the Storage byte count upon creation

A Storage object may be created with an existing storage bottle. For
example, if you navigate from site.com/page1 to site.com/page2, they
will have different localStorage objects, but will use the same bottle
for actual storage.

Previously, if page1 set some key/value item, we would initialize the
byte count to 0 on page2 despite having a non-empty bottle. Thus, if
page2 set a smaller value with the same key, we would overflow the
computed byte count, and all subsequent writes would be rejected.

This was seen navigating from the chess.com home page to the daily
puzzle page.
This commit is contained in:
Timothy Flynn 2025-03-18 13:22:31 -04:00 committed by Jelle Raaijmakers
parent 31da70bbfc
commit 4dfc29356d
Notes: github-actions[bot] 2025-03-18 19:35:13 +00:00
4 changed files with 26 additions and 0 deletions

View file

@ -46,6 +46,9 @@ Storage::Storage(JS::Realm& realm, Type type, NonnullRefPtr<StorageAPI::StorageB
.named_property_deleter_has_identifier = true,
};
for (auto const& item : map())
m_stored_bytes += item.key.byte_count() + item.value.byte_count();
all_storages().set(*this);
}

View file

@ -0,0 +1,4 @@
<script>
localStorage.setItem("foo", "barbaz");
parent.postMessage("local storage set", "*");
</script>

View file

@ -0,0 +1,2 @@
barbaz
bar

View file

@ -0,0 +1,17 @@
<iframe id="frame" src="../../data/local-storage-iframe.html"></iframe>
<script src="../include.js"></script>
<script>
asyncTest(done => {
window.onmessage = () => {
try {
println(localStorage.getItem("foo"));
localStorage.setItem("foo", "bar");
println(localStorage.getItem("foo"));
} catch (e) {
println(e);
}
done();
};
});
</script>