Fix loading very large torrents. Closes #8449.

`torrent_info` constructor has default limits that can't be changed via
parameters, so we handle the loading process manually and explicitly
specifiy the limits to `bdecode()`.
The token_limit is also changed to 10000000.
This commit is contained in:
Chocobo1 2018-02-20 01:02:57 +08:00
parent edef85fa3e
commit f5fc2d52b8
No known key found for this signature in database
GPG key ID: 210D9C873253A68C
2 changed files with 46 additions and 5 deletions

View file

@ -76,13 +76,51 @@ TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
{ {
if (error)
error->clear();
QFile file {path};
if (!file.open(QIODevice::ReadOnly)) {
if (error)
*error = file.errorString();
return TorrentInfo();
}
const qint64 fileSizeLimit = 100 * 1024 * 1024; // 100 MB
if (file.size() > fileSizeLimit) {
if (error)
*error = tr("File size exceeds max limit %1").arg(fileSizeLimit);
return TorrentInfo();
}
const QByteArray data = file.read(fileSizeLimit);
if (data.size() != file.size()) {
if (error)
*error = tr("Torrent file read error");
return TorrentInfo();
}
file.close();
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
// used in `torrent_info()` constructor
const int depthLimit = 100;
const int tokenLimit = 10000000;
libt::bdecode_node node;
libt::error_code ec; libt::error_code ec;
TorrentInfo info(NativePtr(new libt::torrent_info(Utils::Fs::toNativePath(path).toStdString(), ec))); bdecode(data.constData(), (data.constData() + data.size()), node, ec
if (error) { , nullptr, depthLimit, tokenLimit);
if (ec) if (ec) {
if (error)
*error = QString::fromStdString(ec.message()); *error = QString::fromStdString(ec.message());
else return TorrentInfo();
error->clear(); }
TorrentInfo info {NativePtr(new libt::torrent_info(node, ec))};
if (ec) {
if (error)
*error = QString::fromStdString(ec.message());
return TorrentInfo();
} }
return info; return info;

View file

@ -29,6 +29,7 @@
#ifndef BITTORRENT_TORRENTINFO_H #ifndef BITTORRENT_TORRENTINFO_H
#define BITTORRENT_TORRENTINFO_H #define BITTORRENT_TORRENTINFO_H
#include <QCoreApplication>
#include <QtGlobal> #include <QtGlobal>
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
@ -51,6 +52,8 @@ namespace BitTorrent
class TorrentInfo class TorrentInfo
{ {
Q_DECLARE_TR_FUNCTIONS("TorrentInfo")
public: public:
#if LIBTORRENT_VERSION_NUM < 10100 #if LIBTORRENT_VERSION_NUM < 10100
typedef boost::intrusive_ptr<const libtorrent::torrent_info> NativeConstPtr; typedef boost::intrusive_ptr<const libtorrent::torrent_info> NativeConstPtr;