From 4b87363a20e9a72519f98cc3ace934a170d5b53a Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 4 Sep 2018 22:33:57 +0300
Subject: [PATCH] Check value size before putting to cache db.

---
 .../SourceFiles/data/data_media_types.cpp     |  2 ++
 .../passport/passport_form_controller.cpp     |  3 +++
 .../storage/cache/storage_cache_types.h       | 23 +++++++++---------
 .../SourceFiles/storage/file_download.cpp     | 24 +++++++++++--------
 Telegram/SourceFiles/storage/file_upload.cpp  |  7 ++++--
 Telegram/SourceFiles/storage/localstorage.cpp |  1 +
 Telegram/SourceFiles/ui/images.cpp            |  4 +++-
 7 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp
index d175b7fed..0d6df6a11 100644
--- a/Telegram/SourceFiles/data/data_media_types.cpp
+++ b/Telegram/SourceFiles/data/data_media_types.cpp
@@ -354,6 +354,8 @@ bool MediaPhoto::updateSentMedia(const MTPMessageMedia &media) {
 		}
 		if (image->savedData().isEmpty()) {
 			image->forget();
+		} else if (image->savedData().size() > Storage::kMaxFileInMemory) {
+			return;
 		}
 		Auth().data().cache().putIfEmpty(
 			Data::StorageCacheKey(key),
diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp
index 64785e087..143ff24f5 100644
--- a/Telegram/SourceFiles/passport/passport_form_controller.cpp
+++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp
@@ -2340,6 +2340,9 @@ void FormController::fillDownloadedFile(
 		return;
 	}
 	const auto &bytes = i->uploadData->bytes;
+	if (bytes.size() > Storage::kMaxFileInMemory) {
+		return;
+	}
 	Auth().data().cache().put(
 		Data::DocumentCacheKey(destination.dcId, destination.id),
 		Storage::Cache::Database::TaggedValue(
diff --git a/Telegram/SourceFiles/storage/cache/storage_cache_types.h b/Telegram/SourceFiles/storage/cache/storage_cache_types.h
index 415dc6e46..9e060629d 100644
--- a/Telegram/SourceFiles/storage/cache/storage_cache_types.h
+++ b/Telegram/SourceFiles/storage/cache/storage_cache_types.h
@@ -53,10 +53,21 @@ inline Error Error::NoError() {
 
 namespace details {
 
+using RecordType = uint8;
+using PlaceId = std::array<uint8, 7>;
+using EntrySize = std::array<uint8, 3>;
+using RecordsCount = std::array<uint8, 3>;
+
+constexpr auto kRecordSizeUnknown = size_type(-1);
+constexpr auto kRecordSizeInvalid = size_type(-2);
+constexpr auto kBundledRecordsLimit
+	= size_type(1 << (RecordsCount().size() * 8));
+constexpr auto kDataSizeLimit = size_type(1 << (EntrySize().size() * 8));
+
 struct Settings {
 	size_type maxBundledRecords = 16 * 1024;
 	size_type readBlockSize = 8 * 1024 * 1024;
-	size_type maxDataSize = 10 * 1024 * 1024;
+	size_type maxDataSize = (kDataSizeLimit - 1);
 	crl::time_type writeBundleDelay = 15 * 60 * crl::time_type(1000);
 	size_type staleRemoveChunk = 256;
 
@@ -103,16 +114,6 @@ QString VersionFilePath(const QString &base);
 base::optional<Version> ReadVersionValue(const QString &base);
 bool WriteVersionValue(const QString &base, Version value);
 
-using RecordType = uint8;
-using PlaceId = std::array<uint8, 7>;
-using EntrySize = std::array<uint8, 3>;
-using RecordsCount = std::array<uint8, 3>;
-
-constexpr auto kRecordSizeUnknown = size_type(-1);
-constexpr auto kRecordSizeInvalid = size_type(-2);
-constexpr auto kBundledRecordsLimit = (1 << (RecordsCount().size() * 8));
-constexpr auto kDataSizeLimit = (1 << (EntrySize().size() * 8));
-
 template <typename Record>
 constexpr auto GoodForEncryption = ((sizeof(Record) & 0x0F) == 0);
 
diff --git a/Telegram/SourceFiles/storage/file_download.cpp b/Telegram/SourceFiles/storage/file_download.cpp
index 3735442f5..85dac952d 100644
--- a/Telegram/SourceFiles/storage/file_download.cpp
+++ b/Telegram/SourceFiles/storage/file_download.cpp
@@ -971,11 +971,13 @@ bool mtpFileLoader::feedPart(int offset, bytes::const_span buffer) {
 				|| _locationType == UnknownFileLocation
 				|| _toCache == LoadToCacheAsWell) {
 				if (const auto key = cacheKey()) {
-					Auth().data().cache().put(
-						*key,
-						Storage::Cache::Database::TaggedValue(
-							base::duplicate(_data),
-							_cacheTag));
+					if (_data.size() <= Storage::kMaxFileInMemory) {
+						Auth().data().cache().put(
+							*key,
+							Storage::Cache::Database::TaggedValue(
+								base::duplicate(_data),
+								_cacheTag));
+					}
 				}
 			}
 		}
@@ -1197,11 +1199,13 @@ void webFileLoader::onFinished(const QByteArray &data) {
 
 	if (_localStatus == LocalStatus::NotFound) {
 		if (const auto key = cacheKey()) {
-			Auth().data().cache().put(
-				*key,
-				Storage::Cache::Database::TaggedValue(
-					base::duplicate(_data),
-					_cacheTag));
+			if (_data.size() <= Storage::kMaxFileInMemory) {
+				Auth().data().cache().put(
+					*key,
+					Storage::Cache::Database::TaggedValue(
+						base::duplicate(_data),
+						_cacheTag));
+			}
 		}
 	}
 	_downloader->taskFinished().notify();
diff --git a/Telegram/SourceFiles/storage/file_upload.cpp b/Telegram/SourceFiles/storage/file_upload.cpp
index b821ffc43..9fed8a93a 100644
--- a/Telegram/SourceFiles/storage/file_upload.cpp
+++ b/Telegram/SourceFiles/storage/file_upload.cpp
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "storage/file_upload.h"
 
 #include "storage/localimageloader.h"
+#include "storage/file_download.h"
 #include "data/data_document.h"
 #include "data/data_photo.h"
 #include "data/data_session.h"
@@ -126,7 +127,8 @@ void Uploader::uploadMedia(const FullMsgId &msgId, const SendMediaReady &media)
 			: Auth().data().document(media.document, media.photoThumbs.begin().value());
 		if (!media.data.isEmpty()) {
 			document->setData(media.data);
-			if (document->saveToCache()) {
+			if (document->saveToCache()
+				&& media.data.size() <= Storage::kMaxFileInMemory) {
 				Auth().data().cache().put(
 					document->cacheKey(),
 					Storage::Cache::Database::TaggedValue(
@@ -155,7 +157,8 @@ void Uploader::upload(
 		document->uploadingData = std::make_unique<Data::UploadState>(document->size);
 		if (!file->content.isEmpty()) {
 			document->setData(file->content);
-			if (document->saveToCache()) {
+			if (document->saveToCache()
+				&& file->content.size() <= Storage::kMaxFileInMemory) {
 				Auth().data().cache().put(
 					document->cacheKey(),
 					Storage::Cache::Database::TaggedValue(
diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp
index c4674c242..bd73adbfd 100644
--- a/Telegram/SourceFiles/storage/localstorage.cpp
+++ b/Telegram/SourceFiles/storage/localstorage.cpp
@@ -3011,6 +3011,7 @@ Storage::Cache::Database::Settings cacheSettings() {
 	result.clearOnWrongKey = true;
 	result.totalSizeLimit = _cacheTotalSizeLimit;
 	result.totalTimeLimit = _cacheTotalTimeLimit;
+	result.maxDataSize = Storage::kMaxFileInMemory;
 	return result;
 }
 
diff --git a/Telegram/SourceFiles/ui/images.cpp b/Telegram/SourceFiles/ui/images.cpp
index a82506afc..39fc48dac 100644
--- a/Telegram/SourceFiles/ui/images.cpp
+++ b/Telegram/SourceFiles/ui/images.cpp
@@ -1021,7 +1021,9 @@ void RemoteImage::setImageBytes(
 	_forgot = false;
 
 	const auto location = this->location();
-	if (!location.isNull() && !bytes.isEmpty()) {
+	if (!location.isNull()
+		&& !bytes.isEmpty()
+		&& bytes.size() <= Storage::kMaxFileInMemory) {
 		Auth().data().cache().putIfEmpty(
 			Data::StorageCacheKey(location),
 			Storage::Cache::Database::TaggedValue(