diff --git a/Source/WebKit/NetworkProcess/storage/CacheStorageCache.cpp b/Source/WebKit/NetworkProcess/storage/CacheStorageCache.cpp index 3fa15fe47484c..15d7a9f97b64d 100644 --- a/Source/WebKit/NetworkProcess/storage/CacheStorageCache.cpp +++ b/Source/WebKit/NetworkProcess/storage/CacheStorageCache.cpp @@ -29,11 +29,13 @@ #include "CacheStorageDiskStore.h" #include "CacheStorageManager.h" #include "CacheStorageMemoryStore.h" +#include "Logging.h" #include #include #include #include #include +#include #include #include @@ -289,22 +291,38 @@ void CacheStorageCache::putRecords(Vectorsize(); + if (isSpaceRequestedValid) { + spaceRequested += record.responseBodySize; + if (auto* existingRecord = findExistingRecord(record.request)) + spaceAvailable += existingRecord->size(); + if (spaceRequested.hasOverflowed() || spaceAvailable.hasOverflowed()) + isSpaceRequestedValid = false; + else { + uint64_t spaceUsed = std::min(spaceRequested, spaceAvailable); + spaceRequested -= spaceUsed; + spaceAvailable -= spaceUsed; + } + } return toCacheStorageRecord(WTFMove(record), manager->salt(), m_uniqueName); }); // The request still needs to go through quota check to keep ordering. - if (spaceRequested < 0) + if (!isSpaceRequestedValid) spaceRequested = 0; - manager->requestSpace(spaceRequested, [this, weakThis = WeakPtr { *this }, records = WTFMove(cacheStorageRecords), callback = WTFMove(callback)](bool granted) mutable { + manager->requestSpace(spaceRequested, [this, weakThis = WeakPtr { *this }, records = WTFMove(cacheStorageRecords), callback = WTFMove(callback), isSpaceRequestedValid](bool granted) mutable { if (!weakThis) return callback(makeUnexpected(WebCore::DOMCacheEngine::Error::Internal)); + if (!isSpaceRequestedValid) { + RELEASE_LOG_ERROR(Storage, "CacheStorageCache::putRecords failed because the amount of space requested is invalid"); + return callback(makeUnexpected(WebCore::DOMCacheEngine::Error::Internal)); + } + if (!granted) return callback(makeUnexpected(WebCore::DOMCacheEngine::Error::QuotaExceeded)); diff --git a/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.cpp b/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.cpp index ce666fc685ec6..df82678503028 100644 --- a/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.cpp +++ b/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.cpp @@ -29,6 +29,7 @@ #include "CacheStorageRecord.h" #include "Logging.h" #include "NetworkCacheCoders.h" +#include #include #include #include @@ -461,9 +462,9 @@ static Vector encodeRecordHeader(CacheStorageRecord&& record) return { encoder.span() }; } -static Vector encodeRecordBody(const CacheStorageRecord& record) +static Vector encodeRecordBody(const WebCore::DOMCacheEngine::ResponseBody& body) { - return WTF::switchOn(record.responseBody, [](const Ref& formData) { + return WTF::switchOn(body, [](const Ref& formData) { // FIXME: Store form data body. return Vector { }; }, [&](const Ref& buffer) { @@ -473,6 +474,11 @@ static Vector encodeRecordBody(const CacheStorageRecord& record) }); } +size_t CacheStorageDiskStore::computeRealBodySizeForStorage(const WebCore::DOMCacheEngine::ResponseBody& body) +{ + return encodeRecordBody(body).size(); +} + static Vector encodeRecord(const NetworkCache::Key& key, const Vector& headerData, bool isBodyInline, const Vector& bodyData, const SHA1::Digest& bodyHash, FileSystem::Salt salt) { WTF::Persistence::Encoder encoder; @@ -504,7 +510,7 @@ void CacheStorageDiskStore::writeRecords(Vector&& records, W Vector> recordBlobDatas; for (auto&& record : records) { recordFiles.append(recordFilePath(record.info.key())); - auto bodyData = encodeRecordBody(record); + auto bodyData = encodeRecordBody(record.responseBody); auto bodyHash = computeSHA1(bodyData.span(), m_salt); bool shouldCreateBlob = shouldStoreBodyAsBlob(bodyData); auto recordInfoKey = record.info.key(); diff --git a/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.h b/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.h index b7bffd7deb395..d72727fb30293 100644 --- a/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.h +++ b/Source/WebKit/NetworkProcess/storage/CacheStorageDiskStore.h @@ -31,11 +31,16 @@ #include #include +namespace WebCore::DOMCacheEngine { +using ResponseBody = std::variant, Ref>; +} + namespace WebKit { class CacheStorageDiskStore final : public CacheStorageStore { public: static Ref create(const String& cacheName, const String& path, Ref&&); + static size_t computeRealBodySizeForStorage(const WebCore::DOMCacheEngine::ResponseBody&); private: CacheStorageDiskStore(const String& cacheName, const String& path, Ref&&); diff --git a/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp b/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp index 693cc495066b6..7469f13136632 100644 --- a/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp +++ b/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp @@ -29,6 +29,7 @@ #include "BackgroundFetchChange.h" #include "BackgroundFetchStoreManager.h" #include "CacheStorageCache.h" +#include "CacheStorageDiskStore.h" #include "CacheStorageManager.h" #include "CacheStorageRegistry.h" #include "FileSystemStorageHandleRegistry.h" @@ -50,6 +51,7 @@ #include "StorageAreaRegistry.h" #include "UnifiedOriginStorageLevel.h" #include "WebsiteDataType.h" +#include #include #include #include @@ -1826,12 +1828,15 @@ void NetworkStorageManager::cacheStorageRemoveRecords(WebCore::DOMCacheIdentifie cache->removeRecords(WTFMove(request), WTFMove(options), WTFMove(callback)); } -void NetworkStorageManager::cacheStoragePutRecords(WebCore::DOMCacheIdentifier cacheIdentifier, Vector&& records, WebCore::DOMCacheEngine::RecordIdentifiersCallback&& callback) +void NetworkStorageManager::cacheStoragePutRecords(IPC::Connection& connection, WebCore::DOMCacheIdentifier cacheIdentifier, Vector&& records, WebCore::DOMCacheEngine::RecordIdentifiersCallback&& callback) { RefPtr cache = protectedCacheStorageRegistry()->cache(cacheIdentifier); if (!cache) return callback(makeUnexpected(WebCore::DOMCacheEngine::Error::Internal)); + for (auto& record : records) + MESSAGE_CHECK_COMPLETION(record.responseBodySize >= CacheStorageDiskStore::computeRealBodySizeForStorage(record.responseBody), connection, callback(makeUnexpected(WebCore::DOMCacheEngine::Error::Internal))); + cache->putRecords(WTFMove(records), WTFMove(callback)); } diff --git a/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h b/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h index 15559a3b7eb8b..07529a1a9b55c 100644 --- a/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h +++ b/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h @@ -229,7 +229,7 @@ class NetworkStorageManager final : public IPC::WorkQueueMessageReceiver, public void unlockCacheStorage(IPC::Connection&, const WebCore::ClientOrigin&); void cacheStorageRetrieveRecords(WebCore::DOMCacheIdentifier, WebCore::RetrieveRecordsOptions&&, WebCore::DOMCacheEngine::CrossThreadRecordsCallback&&); void cacheStorageRemoveRecords(WebCore::DOMCacheIdentifier, WebCore::ResourceRequest&&, WebCore::CacheQueryOptions&&, WebCore::DOMCacheEngine::RecordIdentifiersCallback&&); - void cacheStoragePutRecords(WebCore::DOMCacheIdentifier, Vector&&, WebCore::DOMCacheEngine::RecordIdentifiersCallback&&); + void cacheStoragePutRecords(IPC::Connection&, WebCore::DOMCacheIdentifier, Vector&&, WebCore::DOMCacheEngine::RecordIdentifiersCallback&&); void cacheStorageClearMemoryRepresentation(const WebCore::ClientOrigin&, CompletionHandler&&); void cacheStorageRepresentation(CompletionHandler&&);