Title: [250936] trunk
Revision
250936
Author
sihui_...@apple.com
Date
2019-10-09 15:20:29 -0700 (Wed, 09 Oct 2019)

Log Message

IndexedDB: include size of index records in size estimate of put/add task
https://bugs.webkit.org/show_bug.cgi?id=202483

Reviewed by Geoffrey Garen.

Source/WebCore:

SQLiteIDBBackingStore has two tables IndexRecords and Records. For add operation add(VALUE, KEY), we add a new
record to Records table. If we can extract index value from VALUE for some index, we would add a new record to
IndexRecords table.

We estimated the task szie of add task with (KEY_SIZE + VALUE_SIZE), but we didn't count the size that could be
added to the IndexRecords table. This could lead to storage abuse.

Test: storage/indexeddb/request-size-estimate.html

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::putOrAdd):

LayoutTests:

* platform/mac-wk1/TestExpectations:
* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:
* storage/indexeddb/request-size-estimate-expected.txt: Added.
* storage/indexeddb/request-size-estimate.html: Added.
* storage/indexeddb/resources/request-size-estimate.js: Added.
(randomKey):
(randomPropertyValue):
(createObject):
(prepareDatabase):
(onOpenSuccess):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (250935 => 250936)


--- trunk/LayoutTests/ChangeLog	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/LayoutTests/ChangeLog	2019-10-09 22:20:29 UTC (rev 250936)
@@ -1,3 +1,22 @@
+2019-10-09  Sihui Liu  <sihui_...@apple.com>
+
+        IndexedDB: include size of index records in size estimate of put/add task
+        https://bugs.webkit.org/show_bug.cgi?id=202483
+
+        Reviewed by Geoffrey Garen.
+
+        * platform/mac-wk1/TestExpectations:
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+        * storage/indexeddb/request-size-estimate-expected.txt: Added.
+        * storage/indexeddb/request-size-estimate.html: Added.
+        * storage/indexeddb/resources/request-size-estimate.js: Added.
+        (randomKey):
+        (randomPropertyValue):
+        (createObject):
+        (prepareDatabase):
+        (onOpenSuccess):
+
 2019-10-09  Chris Dumez  <cdu...@apple.com>
 
         Youtube.com is unable to enter the back/forward cache on macOS

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (250935 => 250936)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2019-10-09 22:20:29 UTC (rev 250936)
@@ -304,6 +304,7 @@
 http/tests/IndexedDB/storage-limit-1.https.html [ Skip ]
 http/tests/IndexedDB/storage-limit-2.https.html [ Skip ]
 storage/indexeddb/storage-limit.html [ Skip ]
+storage/indexeddb/request-size-estimate.html [ Skip ]
 
 # Skip WebRTC for now in WK1
 imported/w3c/web-platform-tests/webrtc [ Skip ]

Modified: trunk/LayoutTests/platform/win/TestExpectations (250935 => 250936)


--- trunk/LayoutTests/platform/win/TestExpectations	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/LayoutTests/platform/win/TestExpectations	2019-10-09 22:20:29 UTC (rev 250936)
@@ -2417,6 +2417,7 @@
 http/tests/xmlhttprequest/web-apps/013.html
 
 storage/indexeddb/storage-limit.html [ Skip ]
+storage/indexeddb/request-size-estimate.html [ Skip ]
 http/tests/IndexedDB/storage-limit.https.html [ Skip ]
 http/tests/IndexedDB/storage-limit-1.https.html [ Skip ]
 http/tests/IndexedDB/storage-limit-2.https.html [ Skip ]

Modified: trunk/LayoutTests/platform/wincairo/TestExpectations (250935 => 250936)


--- trunk/LayoutTests/platform/wincairo/TestExpectations	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/LayoutTests/platform/wincairo/TestExpectations	2019-10-09 22:20:29 UTC (rev 250936)
@@ -1471,6 +1471,7 @@
 storage/indexeddb/objectstore-basics.html [ Failure Pass ]
 storage/indexeddb/objectstore-cursor.html [ Pass Timeout ]
 storage/indexeddb/storage-limit.html [ Failure ]
+storage/indexeddb/request-size-estimate.html [ Failure ]
 storage/indexeddb/structured-clone.html [ Pass Timeout ]
 storage/indexeddb/version-change-abort.html [ Failure Pass ]
 storage/indexeddb/wasm-exceptions.html [ Failure ]

Added: trunk/LayoutTests/storage/indexeddb/request-size-estimate-expected.txt (0 => 250936)


--- trunk/LayoutTests/storage/indexeddb/request-size-estimate-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/request-size-estimate-expected.txt	2019-10-09 22:20:29 UTC (rev 250936)
@@ -0,0 +1,24 @@
+This test verifies that estimated size of IDB database task is not smaller than or close to actual space increase (maybe subject to our implementation of backing store.)
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+
+prepareDatabase():
+Create 20 indexes
+
+onOpenSuccess():
+db = event.target.result
+store = db.transaction('store', 'readwrite').objectStore('store')
+request = store.add(createObject(), randomKey(keySize))
+PASS 'error' in request is true
+PASS request.error.code is DOMException.QUOTA_EXCEEDED_ERR
+PASS request.error.name is "QuotaExceededError"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/storage/indexeddb/request-size-estimate.html (0 => 250936)


--- trunk/LayoutTests/storage/indexeddb/request-size-estimate.html	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/request-size-estimate.html	2019-10-09 22:20:29 UTC (rev 250936)
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/storage/indexeddb/resources/request-size-estimate.js (0 => 250936)


--- trunk/LayoutTests/storage/indexeddb/resources/request-size-estimate.js	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/request-size-estimate.js	2019-10-09 22:20:29 UTC (rev 250936)
@@ -0,0 +1,72 @@
+if (this.importScripts) {
+    importScripts('../../../resources/js-test.js');
+    importScripts('shared.js');
+}
+
+if (window.testRunner)
+    testRunner.setAllowStorageQuotaIncrease(false);
+
+description('This test verifies that estimated size of IDB database task is not smaller than or close to actual space increase (maybe subject to our implementation of backing store.)');
+
+const quota = 400 * 1024; // Current default quota for test.
+const indexCount = 20;
+const indexValueSize = 1024;
+const keySize = 1024;
+
+indexedDBTest(prepareDatabase, onOpenSuccess);
+
+function randomKey(length) {
+    var str = "";
+    for (var i = 0; i < length; i++)
+        str += (Math.floor(Math.random() * 10))
+    return str;
+}
+
+function randomPropertyValue(length) {
+    var value = [];
+    for (var i = 0; i < length; i++)
+        value.push(Math.floor(Math.random() * 10))
+    return value;
+}
+
+function createObject() {
+    var obj = { };
+    for (var i = 0; i < indexCount; i++) 
+        obj["index" + i] = randomPropertyValue(indexValueSize);
+
+    return obj;
+}
+
+function prepareDatabase(event)
+{
+    preamble(event);
+    db = event.target.result;
+    store = db.createObjectStore('store');
+    var indexes = [];
+
+    debug("Create " + indexCount + " indexes");
+    // This is an extreme case where each of indexes is composed of all properties of the object.
+    for (var i = 0; i < indexCount; i ++)
+        indexes.push("index" + i);
+    for (var i = 0; i < indexCount; i ++)
+        store.createIndex("allIndexes" + i, indexes);
+}
+
+function onOpenSuccess(event)
+{
+    preamble(event);
+    evalAndLog("db = event.target.result");
+    evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
+    request = evalAndLog("request = store.add(createObject(), randomKey(keySize))");
+    request._onerror_ = () => {
+        shouldBeTrue("'error' in request");
+        shouldBe("request.error.code", "DOMException.QUOTA_EXCEEDED_ERR");
+        shouldBeEqualToString("request.error.name", "QuotaExceededError");
+
+        finishJSTest();
+    }
+    request._onsuccess_ = () => {
+        testFailed("Add operation should fail because task size is bigger than space available");
+        finishJSTest();
+    }
+}
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (250935 => 250936)


--- trunk/Source/WebCore/ChangeLog	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/Source/WebCore/ChangeLog	2019-10-09 22:20:29 UTC (rev 250936)
@@ -1,3 +1,22 @@
+2019-10-09  Sihui Liu  <sihui_...@apple.com>
+
+        IndexedDB: include size of index records in size estimate of put/add task
+        https://bugs.webkit.org/show_bug.cgi?id=202483
+
+        Reviewed by Geoffrey Garen.
+
+        SQLiteIDBBackingStore has two tables IndexRecords and Records. For add operation add(VALUE, KEY), we add a new 
+        record to Records table. If we can extract index value from VALUE for some index, we would add a new record to
+        IndexRecords table.
+
+        We estimated the task szie of add task with (KEY_SIZE + VALUE_SIZE), but we didn't count the size that could be
+        added to the IndexRecords table. This could lead to storage abuse.
+
+        Test: storage/indexeddb/request-size-estimate.html
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::putOrAdd):
+
 2019-10-09  Chris Dumez  <cdu...@apple.com>
 
         Youtube.com is unable to enter the back/forward cache on macOS

Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (250935 => 250936)


--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp	2019-10-09 22:03:29 UTC (rev 250935)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp	2019-10-09 22:20:29 UTC (rev 250936)
@@ -1228,6 +1228,11 @@
     LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
 
     auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(value);
+    ASSERT(m_databaseInfo);
+    auto* objectStore = m_databaseInfo->infoForExistingObjectStore(requestData.objectStoreIdentifier());
+    if (objectStore)
+        taskSize += objectStore->indexNames().size() * taskSize;
+
     requestSpace(transaction, taskSize, "putOrAdd", [this, taskSize, requestData, keyData, value, callback = WTFMove(callback), overwriteMode](auto error) mutable {
         if (!error.isNull() && *error.code() != QuotaExceededError) {
             callback(WTFMove(error), { });
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to