From 511796f74ef8028d57721666e26e4c90ba61abd2 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Fri, 10 Feb 2017 20:33:21 +0800 Subject: [PATCH] Replace rand() by a true uniform distribution generator --- src/app/main.cpp | 1 - src/base/CMakeLists.txt | 2 ++ src/base/base.pri | 2 ++ src/base/bittorrent/session.cpp | 3 +- src/base/utils/random.cpp | 53 ++++++++++++++++++++++++++++ src/base/utils/random.h | 44 +++++++++++++++++++++++ src/gui/optionsdlg.cpp | 3 +- src/webui/abstractwebapplication.cpp | 7 ++-- 8 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 src/base/utils/random.cpp create mode 100644 src/base/utils/random.h diff --git a/src/app/main.cpp b/src/app/main.cpp index d82c0e038..3591b271b 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -259,7 +259,6 @@ int main(int argc, char *argv[]) && isatty(fileno(stdout)))) return EXIT_FAILURE; #endif - srand(time(0)); #ifdef DISABLE_GUI if (params.shouldDaemonize) { app.reset(); // Destroy current application diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index fa4ba824e..68b19dfca 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -44,6 +44,7 @@ rss/rssmanager.h utils/fs.h utils/gzip.h utils/misc.h +utils/random.h utils/string.h filesystemwatcher.h iconprovider.h @@ -103,6 +104,7 @@ rss/rssmanager.cpp utils/fs.cpp utils/gzip.cpp utils/misc.cpp +utils/random.cpp utils/string.cpp filesystemwatcher.cpp iconprovider.cpp diff --git a/src/base/base.pri b/src/base/base.pri index b6310ae4f..6de6d98a5 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -52,6 +52,7 @@ HEADERS += \ $$PWD/utils/fs.h \ $$PWD/utils/gzip.h \ $$PWD/utils/misc.h \ + $$PWD/utils/random.h \ $$PWD/utils/string.h \ $$PWD/unicodestrings.h \ $$PWD/torrentfileguard.h \ @@ -107,6 +108,7 @@ SOURCES += \ $$PWD/utils/fs.cpp \ $$PWD/utils/gzip.cpp \ $$PWD/utils/misc.cpp \ + $$PWD/utils/random.cpp \ $$PWD/utils/string.cpp \ $$PWD/torrentfileguard.cpp \ $$PWD/torrentfilter.cpp \ diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 05941f78c..d6efc8fad 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -76,6 +76,7 @@ #include "base/unicodestrings.h" #include "base/utils/misc.h" #include "base/utils/fs.h" +#include "base/utils/random.h" #include "base/utils/string.h" #include "cachestatus.h" #include "magneturi.h" @@ -2200,7 +2201,7 @@ void Session::setSaveResumeDataInterval(uint value) int Session::port() const { - static int randomPort = rand() % 64512 + 1024; + static int randomPort = Utils::Random::rand(1024, 65535); if (useRandomPort()) return randomPort; return m_port; diff --git a/src/base/utils/random.cpp b/src/base/utils/random.cpp new file mode 100644 index 000000000..7e56126b9 --- /dev/null +++ b/src/base/utils/random.cpp @@ -0,0 +1,53 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Mike Tzou + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + */ + +#include "random.h" + +#include +#include +#include + +// on some platform `std::random_device` may generate the same number sequence +static bool hasTrueRandomDevice{ std::random_device{}() != std::random_device{}() }; +static thread_local std::mt19937 generator{ + hasTrueRandomDevice + ? std::random_device{}() + : (std::random_device::result_type) std::chrono::system_clock::now().time_since_epoch().count() +}; + +uint32_t Utils::Random::rand(const uint32_t min, const uint32_t max) +{ + // better replacement for `std::rand`, don't use this for real cryptography application + // min <= returned_value <= max + assert(min <= max); + + // new distribution is cheap: http://stackoverflow.com/a/19036349 + std::uniform_int_distribution uniform(min, max); + return uniform(generator); +} diff --git a/src/base/utils/random.h b/src/base/utils/random.h new file mode 100644 index 000000000..d4198deca --- /dev/null +++ b/src/base/utils/random.h @@ -0,0 +1,44 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Mike Tzou + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + */ + +#ifndef UTILS_RANDOM_H +#define UTILS_RANDOM_H + +#include +#include + +namespace Utils +{ + namespace Random + { + uint32_t rand(uint32_t min = 0, uint32_t max = UINT32_MAX); + } +} + +#endif // UTILS_FS_H diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index ce82dc750..10e3c62ca 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -58,6 +58,7 @@ #include "base/torrentfileguard.h" #include "base/unicodestrings.h" #include "base/utils/fs.h" +#include "base/utils/random.h" #include "addnewtorrentdialog.h" #include "advancedsettings.h" #include "guiiconprovider.h" @@ -1002,7 +1003,7 @@ int OptionsDialog::getPort() const void OptionsDialog::on_randomButton_clicked() { // Range [1024: 65535] - m_ui->spinPort->setValue(rand() % 64512 + 1024); + m_ui->spinPort->setValue(Utils::Random::rand(1024, 65535)); } int OptionsDialog::getEncryptionSetting() const diff --git a/src/webui/abstractwebapplication.cpp b/src/webui/abstractwebapplication.cpp index b8f8c0575..c0e42bf0a 100644 --- a/src/webui/abstractwebapplication.cpp +++ b/src/webui/abstractwebapplication.cpp @@ -26,6 +26,8 @@ * exception statement from your version. */ +#include "abstractwebapplication.h" + #include #include #include @@ -37,8 +39,8 @@ #include "base/preferences.h" #include "base/utils/fs.h" +#include "base/utils/random.h" #include "websessiondata.h" -#include "abstractwebapplication.h" // UnbanTimer @@ -219,13 +221,12 @@ QString AbstractWebApplication::generateSid() { QString sid; - qsrand(QDateTime::currentDateTime().toTime_t()); do { const size_t size = 6; quint32 tmp[size]; for (size_t i = 0; i < size; ++i) - tmp[i] = qrand(); + tmp[i] = Utils::Random::rand(); sid = QByteArray::fromRawData(reinterpret_cast(tmp), sizeof(quint32) * size).toBase64(); }