Skip to content

Commit

Permalink
QRandomGenerator: let qt_initial_random_value() return 128 bits of data
Browse files Browse the repository at this point in the history
It's how much there is in Linux's AT_RANDOM block.

I've also removed the check for validity. It's highly unlikely that 128
bits are bad.

Change-Id: Id2983978ad544ff79911fffd16723161ea7ec315
Reviewed-by: Qt CI Bot <[email protected]>
Reviewed-by: Lars Knoll <[email protected]>
Reviewed-by: Allan Sandfeld Jensen <[email protected]>
  • Loading branch information
thiagomacieira committed May 23, 2021
1 parent 928ce40 commit a5ff715
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 29 deletions.
36 changes: 10 additions & 26 deletions src/corelib/global/qrandom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,8 +1296,8 @@ quint64 QRandomGenerator::_fillRange(void *buffer, qptrdiff count)

// helper function to call fillBuffer, since we need something to be
// argument-dependent
template <typename Generator, typename FillBufferType>
static qsizetype callFillBuffer(FillBufferType f, quintptr *v)
template <typename Generator, typename FillBufferType, typename T>
static qsizetype callFillBuffer(FillBufferType f, T *v)
{
if constexpr (std::is_member_function_pointer_v<FillBufferType>) {
// member function, need an object
Expand All @@ -1318,45 +1318,29 @@ static qsizetype callFillBuffer(FillBufferType f, quintptr *v)
Note: on some systems, this functionn may rerturn the same value every time
it is called.
*/
quintptr qt_initial_random_value() noexcept
QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
{
auto acceptableSeed = [](size_t v) {
// two values are reserved: 0 to indicate uninitialized and 1 to
// indicate deterministic seed
return Q_LIKELY(v > 1);
};
quintptr v = 0;

#if QT_CONFIG(getauxval) && defined(AT_RANDOM)
// We actually have 16 bytes, but this will do
auto at_random_ptr = reinterpret_cast<size_t *>(getauxval(AT_RANDOM));
if (at_random_ptr) {
v = qFromUnaligned<quintptr>(at_random_ptr);
if (acceptableSeed(v))
return v;
}
if (at_random_ptr)
return qFromUnaligned<QRandomGenerator::InitialRandomData>(at_random_ptr);
#endif

// bypass the hardware RNG, which would mean initializing qsimd.cpp

QRandomGenerator::InitialRandomData v;
for (int attempts = 16; attempts; --attempts) {
using Generator = QRandomGenerator::SystemGenerator;
auto fillBuffer = &Generator::fillBuffer;
if (callFillBuffer<Generator>(fillBuffer, &v) != sizeof(v))
continue;

// check if it is static
if (acceptableSeed(v))
return v;
return v;
}

quint32 u32[2] = {};
forever {
fallback_fill(u32, sizeof(v) / sizeof(quint32));
v = u32[0] | (quint64(u32[1]) << 32);
if (acceptableSeed(v))
break;
}
quint32 data[sizeof(v) / sizeof(quint32)];
fallback_fill(data, std::size(data));
memcpy(v.data, data, sizeof(v.data));
return v;
}

Expand Down
5 changes: 4 additions & 1 deletion src/corelib/global/qrandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,10 @@ class QRandomGenerator
private:
Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);

friend quintptr qt_initial_random_value() noexcept;
struct InitialRandomData {
quintptr data[16 / sizeof(quintptr)];
};
friend InitialRandomData qt_initial_random_value() noexcept;
friend class QRandomGenerator64;
struct SystemGenerator;
struct SystemAndGlobalGenerators;
Expand Down
3 changes: 2 additions & 1 deletion src/corelib/global/qrandom_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
//

#include "qglobal_p.h"
#include <qrandom.h>
#include <private/qsimd_p.h>

QT_BEGIN_NAMESPACE
Expand Down Expand Up @@ -80,7 +81,7 @@ static const struct
} qt_randomdevice_control;
#endif

quintptr qt_initial_random_value() noexcept;
QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept;

QT_END_NAMESPACE

Expand Down
3 changes: 2 additions & 1 deletion src/corelib/tools/qhash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@ static size_t qt_create_qhash_seed(HashCreationMode mode)
}
seed = 1; // QHashSeed::globalSeed subtracts 1
} else if (mode == Initial) {
seed = qt_initial_random_value();
auto data = qt_initial_random_value();
seed = data.data[0] ^ data.data[1];
} else if (sizeof(seed) > sizeof(uint)) {
seed = QRandomGenerator::system()->generate64();
} else {
Expand Down

0 comments on commit a5ff715

Please sign in to comment.