QUuid, QHttpMultipart and QHash: use QRandomGenerator
QRandomGenerator can produce more than 31 bits of data. And it uses /dev/urandom for us on Unix, so QHash does not need to duplicate that part. Change-Id: Icd0e0d4b27cb4e5eb892fffd14b52a0d91f179eb Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
5483b30868
commit
f17095653e
@ -40,14 +40,13 @@
|
||||
|
||||
#include "quuid.h"
|
||||
|
||||
#include "qcryptographichash.h"
|
||||
#include "qdatastream.h"
|
||||
#include "qendian.h"
|
||||
#include "qdebug.h"
|
||||
#include "qendian.h"
|
||||
#include "qrandom.h"
|
||||
#include "private/qtools_p.h"
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#include "qcryptographichash.h"
|
||||
#endif
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
|
||||
@ -918,17 +917,10 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
|
||||
/*!
|
||||
\fn QUuid QUuid::createUuid()
|
||||
|
||||
On any platform other than Windows, this function returns a new
|
||||
UUID with variant QUuid::DCE and version QUuid::Random. If
|
||||
the /dev/urandom device exists, then the numbers used to construct
|
||||
the UUID will be of cryptographic quality, which will make the UUID
|
||||
unique. Otherwise, the numbers of the UUID will be obtained from
|
||||
the local pseudo-random number generator (qrand(), which is seeded
|
||||
by qsrand()) which is usually not of cryptograhic quality, which
|
||||
means that the UUID can't be guaranteed to be unique.
|
||||
|
||||
On a Windows platform, a GUID is generated, which almost certainly
|
||||
\e{will} be unique, on this or any other system, networked or not.
|
||||
On any platform other than Windows, this function returns a new UUID with
|
||||
variant QUuid::DCE and version QUuid::Random. On Windows, a GUID is
|
||||
generated using the Windows API and will be of the type that the API
|
||||
decides to create.
|
||||
|
||||
\sa variant(), version()
|
||||
*/
|
||||
@ -948,82 +940,12 @@ QUuid QUuid::createUuid()
|
||||
|
||||
#else // Q_OS_WIN
|
||||
|
||||
QT_BEGIN_INCLUDE_NAMESPACE
|
||||
#include "qdatetime.h"
|
||||
#include "qfile.h"
|
||||
#include "qthreadstorage.h"
|
||||
#include <stdlib.h> // for RAND_MAX
|
||||
QT_END_INCLUDE_NAMESPACE
|
||||
|
||||
#if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_UNIX)
|
||||
Q_GLOBAL_STATIC(QThreadStorage<QFile *>, devUrandomStorage);
|
||||
#endif
|
||||
|
||||
QUuid QUuid::createUuid()
|
||||
{
|
||||
QUuid result;
|
||||
QUuid result(Qt::Uninitialized);
|
||||
uint *data = &(result.data1);
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
QFile *devUrandom;
|
||||
# if !defined(QT_BOOTSTRAPPED)
|
||||
devUrandom = devUrandomStorage()->localData();
|
||||
if (!devUrandom) {
|
||||
devUrandom = new QFile(QLatin1String("/dev/urandom"));
|
||||
devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
devUrandomStorage()->setLocalData(devUrandom);
|
||||
}
|
||||
# else
|
||||
QFile file(QLatin1String("/dev/urandom"));
|
||||
devUrandom = &file;
|
||||
devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
# endif
|
||||
enum { AmountToRead = 4 * sizeof(uint) };
|
||||
if (devUrandom->isOpen()
|
||||
&& devUrandom->read((char *) data, AmountToRead) == AmountToRead) {
|
||||
// we got what we wanted, nothing more to do
|
||||
;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
static const int intbits = sizeof(int)*8;
|
||||
static int randbits = 0;
|
||||
if (!randbits) {
|
||||
int r = 0;
|
||||
int max = RAND_MAX;
|
||||
do { ++r; } while ((max=max>>1));
|
||||
randbits = r;
|
||||
}
|
||||
|
||||
// Seed the PRNG once per thread with a combination of current time, a
|
||||
// stack address and a serial counter (since thread stack addresses are
|
||||
// re-used).
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static QThreadStorage<int *> uuidseed;
|
||||
if (!uuidseed.hasLocalData())
|
||||
{
|
||||
int *pseed = new int;
|
||||
static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
qsrand(*pseed = QDateTime::currentSecsSinceEpoch()
|
||||
+ quintptr(&pseed)
|
||||
+ 2 + serial.fetchAndAddRelaxed(1));
|
||||
uuidseed.setLocalData(pseed);
|
||||
}
|
||||
#else
|
||||
static bool seeded = false;
|
||||
if (!seeded)
|
||||
qsrand(QDateTime::currentSecsSinceEpoch()
|
||||
+ quintptr(&seeded));
|
||||
#endif
|
||||
|
||||
int chunks = 16 / sizeof(uint);
|
||||
while (chunks--) {
|
||||
uint randNumber = 0;
|
||||
for (int filled = 0; filled < intbits; filled += randbits)
|
||||
randNumber |= qrand()<<filled;
|
||||
*(data+chunks) = randNumber;
|
||||
}
|
||||
}
|
||||
enum { AmountToRead = 4 };
|
||||
QRandomGenerator::fillRange(data, AmountToRead);
|
||||
|
||||
result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
|
||||
result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
|
||||
|
@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QUuid
|
||||
{
|
||||
QUuid(Qt::Initialization) {}
|
||||
public:
|
||||
enum Variant {
|
||||
VarUnknown =-1,
|
||||
|
@ -63,13 +63,9 @@
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#include <qcoreapplication.h>
|
||||
#include <qrandom.h>
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <stdio.h>
|
||||
#include "private/qcore_unix_p.h"
|
||||
#endif // Q_OS_UNIX
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -298,39 +294,7 @@ static uint qt_create_qhash_seed()
|
||||
return seed;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
int randomfd = qt_safe_open("/dev/urandom", O_RDONLY);
|
||||
if (randomfd == -1)
|
||||
randomfd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK);
|
||||
if (randomfd != -1) {
|
||||
if (qt_safe_read(randomfd, reinterpret_cast<char *>(&seed), sizeof(seed)) == sizeof(seed)) {
|
||||
qt_safe_close(randomfd);
|
||||
return seed;
|
||||
}
|
||||
qt_safe_close(randomfd);
|
||||
}
|
||||
#endif // Q_OS_UNIX
|
||||
|
||||
#if defined(Q_OS_WIN32) && !defined(Q_CC_GNU)
|
||||
errno_t err;
|
||||
err = rand_s(&seed);
|
||||
if (err == 0)
|
||||
return seed;
|
||||
#endif // Q_OS_WIN32
|
||||
|
||||
// general fallback: initialize from the current timestamp, pid,
|
||||
// and address of a stack-local variable
|
||||
quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
seed ^= timestamp;
|
||||
seed ^= (timestamp >> 32);
|
||||
|
||||
quint64 pid = QCoreApplication::applicationPid();
|
||||
seed ^= pid;
|
||||
seed ^= (pid >> 32);
|
||||
|
||||
quintptr seedPtr = reinterpret_cast<quintptr>(&seed);
|
||||
seed ^= seedPtr;
|
||||
seed ^= (qulonglong(seedPtr) >> 32); // no-op on 32-bit platforms
|
||||
seed = QRandomGenerator::get32();
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
return seed;
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "qhttpmultipart_p.h"
|
||||
#include "QtCore/qdatetime.h" // for initializing the random number generator with QTime
|
||||
#include "QtCore/qmutex.h"
|
||||
#include "QtCore/qthreadstorage.h"
|
||||
#include "QtCore/qrandom.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -431,23 +431,16 @@ void QHttpPartPrivate::checkHeaderCreated() const
|
||||
}
|
||||
}
|
||||
|
||||
Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage);
|
||||
|
||||
QHttpMultiPartPrivate::QHttpMultiPartPrivate() : contentType(QHttpMultiPart::MixedType), device(new QHttpMultiPartIODevice(this))
|
||||
{
|
||||
if (!seedCreatedStorage()->hasLocalData()) {
|
||||
qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast<quintptr>(this));
|
||||
seedCreatedStorage()->setLocalData(new bool(true));
|
||||
}
|
||||
|
||||
boundary = QByteArray("boundary_.oOo._")
|
||||
+ QByteArray::number(qrand()).toBase64()
|
||||
+ QByteArray::number(qrand()).toBase64()
|
||||
+ QByteArray::number(qrand()).toBase64();
|
||||
// 24 random bytes, becomes 32 characters when encoded to Base64
|
||||
quint32 random[6];
|
||||
QRandomGenerator::fillRange(random);
|
||||
boundary = "boundary_.oOo._"
|
||||
+ QByteArray::fromRawData(reinterpret_cast<char *>(random), sizeof(random)).toBase64();
|
||||
|
||||
// boundary must not be longer than 70 characters, see RFC 2046, section 5.1.1
|
||||
if (boundary.count() > 70)
|
||||
boundary = boundary.left(70);
|
||||
Q_ASSERT(boundary.count() <= 70);
|
||||
}
|
||||
|
||||
qint64 QHttpMultiPartIODevice::size() const
|
||||
|
Loading…
x
Reference in New Issue
Block a user