Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't read unlimited data from files #19095

Merged
merged 1 commit into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions src/base/bittorrent/bencoderesumedatastorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QRegularExpression>
#include <QThread>

Expand Down Expand Up @@ -133,17 +134,19 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::load(cons
const Path fastresumePath = path() / Path(idString + u".fastresume");
const Path torrentFilePath = path() / Path(idString + u".torrent");

QFile resumeDataFile {fastresumePath.data()};
if (!resumeDataFile.open(QIODevice::ReadOnly))
return nonstd::make_unexpected(tr("Cannot read file %1: %2").arg(fastresumePath.toString(), resumeDataFile.errorString()));
const auto resumeDataReadResult = Utils::IO::readFile(fastresumePath, MAX_TORRENT_SIZE);
if (!resumeDataReadResult)
return nonstd::make_unexpected(resumeDataReadResult.error().message);

QFile metadataFile {torrentFilePath.data()};
if (metadataFile.exists() && !metadataFile.open(QIODevice::ReadOnly))
return nonstd::make_unexpected(tr("Cannot read file %1: %2").arg(torrentFilePath.toString(), metadataFile.errorString()));

const QByteArray data = resumeDataFile.readAll();
const QByteArray metadata = (metadataFile.isOpen() ? metadataFile.readAll() : "");
const auto metadataReadResult = Utils::IO::readFile(torrentFilePath, MAX_TORRENT_SIZE);
if (!metadataReadResult)
{
if (metadataReadResult.error().status != Utils::IO::ReadError::NotExist)
return nonstd::make_unexpected(metadataReadResult.error().message);
}

const QByteArray data = resumeDataReadResult.value();
const QByteArray metadata = metadataReadResult.value_or(QByteArray());
return loadTorrentResumeData(data, metadata);
}

Expand All @@ -161,6 +164,8 @@ void BitTorrent::BencodeResumeDataStorage::doLoadAll() const

void BitTorrent::BencodeResumeDataStorage::loadQueue(const Path &queueFilename)
{
const int lineMaxLength = 48;

QFile queueFile {queueFilename.data()};
if (!queueFile.exists())
return;
Expand All @@ -175,7 +180,7 @@ void BitTorrent::BencodeResumeDataStorage::loadQueue(const Path &queueFilename)
int start = 0;
while (true)
{
const auto line = QString::fromLatin1(queueFile.readLine().trimmed());
const auto line = QString::fromLatin1(queueFile.readLine(lineMaxLength).trimmed());
if (line.isEmpty())
break;

Expand Down
1 change: 0 additions & 1 deletion src/base/bittorrent/dbresumedatastorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@

#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QMutex>
#include <QSet>
#include <QSqlDatabase>
Expand Down
20 changes: 10 additions & 10 deletions src/base/bittorrent/sessionimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QHostAddress>
#include <QJsonArray>
#include <QJsonDocument>
Expand Down Expand Up @@ -5033,8 +5032,8 @@ void SessionImpl::loadCategories()
{
m_categories.clear();

QFile confFile {(specialFolderLocation(SpecialFolder::Config) / CATEGORIES_FILE_NAME).data()};
if (!confFile.exists())
const Path path = specialFolderLocation(SpecialFolder::Config) / CATEGORIES_FILE_NAME;
if (!path.exists())
{
// TODO: Remove the following upgrade code in v4.5
// == BEGIN UPGRADE CODE ==
Expand All @@ -5045,26 +5044,27 @@ void SessionImpl::loadCategories()
// return;
}

if (!confFile.open(QFile::ReadOnly))
const int fileMaxSize = 1024 * 1024;
const auto readResult = Utils::IO::readFile(path, fileMaxSize);
if (!readResult)
{
LogMsg(tr("Failed to load Categories. File: \"%1\". Error: \"%2\"")
.arg(confFile.fileName(), confFile.errorString()), Log::CRITICAL);
LogMsg(tr("Failed to load Categories. %1").arg(readResult.error().message), Log::WARNING);
Chocobo1 marked this conversation as resolved.
Show resolved Hide resolved
return;
}

QJsonParseError jsonError;
const QJsonDocument jsonDoc = QJsonDocument::fromJson(confFile.readAll(), &jsonError);
const QJsonDocument jsonDoc = QJsonDocument::fromJson(readResult.value(), &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
LogMsg(tr("Failed to parse Categories configuration. File: \"%1\". Error: \"%2\"")
.arg(confFile.fileName(), jsonError.errorString()), Log::WARNING);
.arg(path.toString(), jsonError.errorString()), Log::WARNING);
return;
}

if (!jsonDoc.isObject())
{
LogMsg(tr("Failed to load Categories configuration. File: \"%1\". Reason: invalid data format")
.arg(confFile.fileName()), Log::WARNING);
LogMsg(tr("Failed to load Categories configuration. File: \"%1\". Error: \"Invalid data format\"")
.arg(path.toString()), Log::WARNING);
return;
}

Expand Down
1 change: 0 additions & 1 deletion src/base/bittorrent/torrentimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@

#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QPointer>
#include <QSet>
#include <QStringList>
Expand Down
20 changes: 6 additions & 14 deletions src/base/bittorrent/torrentinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,20 @@ nonstd::expected<TorrentInfo, QString> TorrentInfo::load(const QByteArray &data)

nonstd::expected<TorrentInfo, QString> TorrentInfo::loadFromFile(const Path &path) noexcept
{
QFile file {path.data()};
if (!file.open(QIODevice::ReadOnly))
return nonstd::make_unexpected(file.errorString());

if (file.size() > MAX_TORRENT_SIZE)
return nonstd::make_unexpected(tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE)));

QByteArray data;
try
{
data = file.readAll();
const auto readResult = Utils::IO::readFile(path, MAX_TORRENT_SIZE);
if (!readResult)
return nonstd::make_unexpected(readResult.error().message);
data = readResult.value();
}
catch (const std::bad_alloc &e)
{
return nonstd::make_unexpected(tr("Torrent file read error: %1").arg(QString::fromLocal8Bit(e.what())));
return nonstd::make_unexpected(tr("Failed to allocate memory when reading file. File: \"%1\". Error: \"%2\"")
.arg(path.toString(), QString::fromLocal8Bit(e.what())));
}

if (data.size() != file.size())
return nonstd::make_unexpected(tr("Torrent file read error: size mismatch"));

file.close();

return load(data);
}

Expand Down
29 changes: 13 additions & 16 deletions src/base/rss/feed_serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

#include "feed_serializer.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
Expand All @@ -46,23 +45,21 @@ const int ARTICLEDATALIST_TYPEID = qRegisterMetaType<QVector<QVariantHash>>();

void RSS::Private::FeedSerializer::load(const Path &dataFileName, const QString &url)
{
QFile file {dataFileName.data()};

if (!file.exists())
{
emit loadingFinished({});
}
else if (file.open(QFile::ReadOnly))
{
emit loadingFinished(loadArticles(file.readAll(), url));
file.close();
}
else
const int fileMaxSize = 10 * 1024 * 1024;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we could avoid to make this one configurable in near future if we make it dependent from "max articles per feed".

const auto readResult = Utils::IO::readFile(dataFileName, fileMaxSize);
if (!readResult)
{
LogMsg(tr("Couldn't read RSS Session data from %1. Error: %2")
.arg(dataFileName.toString(), file.errorString())
, Log::WARNING);
if (readResult.error().status == Utils::IO::ReadError::NotExist)
{
emit loadingFinished({});
return;
}

LogMsg(tr("Failed to read RSS session data. %1").arg(readResult.error().message), Log::WARNING);
return;
}

emit loadingFinished(loadArticles(readResult.value(), url));
}

void RSS::Private::FeedSerializer::store(const Path &dataFileName, const QVector<QVariantHash> &articlesData)
Expand Down
27 changes: 14 additions & 13 deletions src/base/rss/rss_autodownloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "../logger.h"
#include "../profile.h"
#include "../utils/fs.h"
#include "../utils/io.h"
#include "rss_article.h"
#include "rss_autodownloadrule.h"
#include "rss_feed.h"
Expand Down Expand Up @@ -453,21 +454,21 @@ void AutoDownloader::processJob(const QSharedPointer<ProcessingJob> &job)

void AutoDownloader::load()
{
QFile rulesFile {(m_fileStorage->storageDir() / Path(RULES_FILE_NAME)).data()};

if (!rulesFile.exists())
{
loadRulesLegacy();
}
else if (rulesFile.open(QFile::ReadOnly))
{
loadRules(rulesFile.readAll());
}
else
const qint64 maxFileSize = 10 * 1024 * 1024;
const auto readResult = Utils::IO::readFile((m_fileStorage->storageDir() / Path(RULES_FILE_NAME)), maxFileSize);
if (!readResult)
{
LogMsg(tr("Couldn't read RSS AutoDownloader rules from %1. Error: %2")
.arg(rulesFile.fileName(), rulesFile.errorString()), Log::CRITICAL);
if (readResult.error().status == Utils::IO::ReadError::NotExist)
{
loadRulesLegacy();
return;
}

LogMsg((tr("Failed to read RSS AutoDownloader rules. %1").arg(readResult.error().message)), Log::WARNING);
return;
}

loadRules(readResult.value());
}

void AutoDownloader::loadRules(const QByteArray &data)
Expand Down
31 changes: 17 additions & 14 deletions src/base/rss/rss_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "../profile.h"
#include "../settingsstorage.h"
#include "../utils/fs.h"
#include "../utils/io.h"
#include "rss_article.h"
#include "rss_feed.h"
#include "rss_folder.h"
Expand Down Expand Up @@ -261,33 +262,35 @@ Item *Session::itemByPath(const QString &path) const

void Session::load()
{
QFile itemsFile {(m_confFileStorage->storageDir() / Path(FEEDS_FILE_NAME)).data()};
if (!itemsFile.exists())
{
loadLegacy();
return;
}
const int fileMaxSize = 10 * 1024 * 1024;
const Path path = m_confFileStorage->storageDir() / Path(FEEDS_FILE_NAME);

if (!itemsFile.open(QFile::ReadOnly))
const auto readResult = Utils::IO::readFile(path, fileMaxSize);
if (!readResult)
{
LogMsg(tr("Couldn't read RSS session data. File: \"%1\". Error: \"%2\"")
.arg(itemsFile.fileName(), itemsFile.errorString()), Log::WARNING);
if (readResult.error().status == Utils::IO::ReadError::NotExist)
{
loadLegacy();
return;
}

LogMsg(tr("Failed to read RSS session data. %1").arg(readResult.error().message), Log::WARNING);
return;
}

QJsonParseError jsonError;
const QJsonDocument jsonDoc = QJsonDocument::fromJson(itemsFile.readAll(), &jsonError);
const QJsonDocument jsonDoc = QJsonDocument::fromJson(readResult.value(), &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
LogMsg(tr("Couldn't parse RSS session data. File: \"%1\". Error: \"%2\"")
.arg(itemsFile.fileName(), jsonError.errorString()), Log::WARNING);
LogMsg(tr("Failed to parse RSS session data. File: \"%1\". Error: \"%2\"")
.arg(path.toString(), jsonError.errorString()), Log::WARNING);
return;
}

if (!jsonDoc.isObject())
{
LogMsg(tr("Couldn't load RSS session data. File: \"%1\". Error: Invalid data format.")
.arg(itemsFile.fileName()), Log::WARNING);
LogMsg(tr("Failed to load RSS session data. File: \"%1\". Error: \"Invalid data format.\"")
.arg(path.toString()), Log::WARNING);
return;
}

Expand Down
7 changes: 5 additions & 2 deletions src/base/search/searchpluginmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QFile>
#include <QPointer>
#include <QProcess>
#include <QUrl>
Expand Down Expand Up @@ -517,7 +518,7 @@ void SearchPluginManager::update()
nova.start(Utils::ForeignApps::pythonInfo().executableName, params, QIODevice::ReadOnly);
nova.waitForFinished();

const auto capabilities = QString::fromUtf8(nova.readAll());
const auto capabilities = QString::fromUtf8(nova.readAllStandardOutput());
QDomDocument xmlDoc;
if (!xmlDoc.setContent(capabilities))
{
Expand Down Expand Up @@ -629,13 +630,15 @@ Path SearchPluginManager::pluginPath(const QString &name)

PluginVersion SearchPluginManager::getPluginVersion(const Path &filePath)
{
const int lineMaxLength = 16;

QFile pluginFile {filePath.data()};
if (!pluginFile.open(QIODevice::ReadOnly | QIODevice::Text))
return {};

while (!pluginFile.atEnd())
{
const auto line = QString::fromUtf8(pluginFile.readLine()).remove(u' ');
const auto line = QString::fromUtf8(pluginFile.readLine(lineMaxLength)).remove(u' ');
if (!line.startsWith(u"#VERSION:", Qt::CaseInsensitive)) continue;

const QString versionStr = line.mid(9);
Expand Down
Loading
Loading