Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qrandom.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 Intel Corporation.
2
// Copyright (C) 2021 The Qt Company Ltd.
3
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
// Qt-Security score:critical reason:cryptography
5
6
// for rand_s
7
#
define
_CRT_RAND_S
8
9
#
include
"qrandom.h"
10
#
include
"qrandom_p.h"
11
#
include
<
qendian
.
h
>
12
#
include
<
qmutex
.
h
>
13
#
include
<
qobjectdefs
.
h
>
14
#
include
<
QtCore
/
qtcoreglobal
.
h
>
// for FEATURE macros
15
16
#
include
<
errno
.
h
>
17
18
#
if
QT_CONFIG
(
getauxval
)
19
#
include
<
sys
/
auxv
.
h
>
20
#
endif
21
22
#
if
QT_CONFIG
(
getentropy
)
&&
__has_include
(
<
sys
/
random
.
h
>
)
23
#
include
<
sys
/
random
.
h
>
24
#
elif
!
QT_CONFIG
(
getentropy
)
&&
(
!
defined
(
Q_OS_BSD4
)
||
defined
(
__GLIBC__
)
)
&&
!
defined
(
Q_OS_WIN
)
25
#
include
"qdeadlinetimer.h"
26
#
include
"qhashfunctions.h"
27
#
include
<
cstdio
>
28
#
include
<
cstdlib
>
29
#
include
<
mutex
>
30
#
endif
// !QT_CONFIG(getentropy)
31
32
#
ifdef
Q_OS_UNIX
33
#
include
<
fcntl
.
h
>
34
#
include
<
private
/
qcore_unix_p
.
h
>
35
#
else
36
#
include
<
qt_windows
.
h
>
37
38
// RtlGenRandom is not exported by its name in advapi32.dll, but as SystemFunction036
39
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
40
// Implementation inspired on https://hg.mozilla.org/mozilla-central/file/722fdbff1efc/security/nss/lib/freebl/win_rand.c#l146
41
// Argument why this is safe to use: https://bugzilla.mozilla.org/show_bug.cgi?id=504270
42
extern
"C"
{
43
DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
44
}
45
#
endif
46
47
// This file is too low-level for regular Q_ASSERT (the logging framework may
48
// recurse back), so use regular assert()
49
#
undef
NDEBUG
50
#
undef
Q_ASSERT_X
51
#
undef
Q_ASSERT
52
#
define
Q_ASSERT
(
cond
)
assert
(
cond
)
53
#
define
Q_ASSERT_X
(
cond
,
x
,
msg
)
assert
(
cond
&&
msg
)
54
#
if
defined
(
QT_NO_DEBUG
)
&&
!
defined
(
QT_FORCE_ASSERTS
)
55
#
define
NDEBUG
1
56
#
endif
57
#
include
<
assert
.
h
>
58
59
QT_BEGIN_NAMESPACE
60
61
enum
{
62
// may be "overridden" by a member enum
63
FillBufferNoexcept =
true
64
};
65
66
#
if
defined
(
QT_BUILD_INTERNAL
)
67
QBasicAtomicInteger<uint> qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U);
68
#
endif
69
70
struct
QRandomGenerator::
SystemGenerator
71
{
72
#
if
QT_CONFIG
(
getentropy
)
73
static
qsizetype
fillBuffer
(
void
*
buffer
,
qsizetype
count
)
noexcept
74
{
75
// getentropy can read at most 256 bytes, so break the reading
76
qsizetype
read
= 0;
77
while
(
count
-
read
> 256) {
78
// getentropy can't fail under normal circumstances
79
int
ret
=
getentropy
(
reinterpret_cast
<
uchar
*>(
buffer
) +
read
, 256);
80
Q_ASSERT
(
ret
== 0);
81
Q_UNUSED
(
ret
);
82
read
+= 256;
83
}
84
85
int
ret
=
getentropy
(
reinterpret_cast
<
uchar
*>(
buffer
) +
read
,
count
-
read
);
86
Q_ASSERT
(
ret
== 0);
87
Q_UNUSED
(
ret
);
88
return
count
;
89
}
90
91
#
elif
defined
(
Q_OS_UNIX
)
92
enum
{
FillBufferNoexcept
=
false
};
93
94
QBasicAtomicInt
fdp1
;
// "file descriptor plus 1"
95
int
openDevice
()
96
{
97
int
fd
=
fdp1
.
loadAcquire
() - 1;
98
if
(
fd
!= -1)
99
return
fd
;
100
101
fd
=
qt_safe_open
(
"/dev/urandom"
,
O_RDONLY
);
102
if
(
fd
== -1)
103
fd
=
qt_safe_open
(
"/dev/random"
,
O_RDONLY
|
O_NONBLOCK
);
104
if
(
fd
== -1) {
105
// failed on both, set to -2 so we won't try again
106
fd
= -2;
107
}
108
109
int
opened_fdp1
;
110
if
(
fdp1
.
testAndSetOrdered
(0,
fd
+ 1,
opened_fdp1
))
111
return
fd
;
112
113
// failed, another thread has opened the file descriptor
114
if
(
fd
>= 0)
115
qt_safe_close
(
fd
);
116
return
opened_fdp1
- 1;
117
}
118
119
#
ifdef
Q_CC_GNU
120
// If it's not GCC or GCC-like, then we'll leak the file descriptor
121
__attribute__
((
destructor
))
122
#
endif
123
static
void
closeDevice
()
124
{
125
int
fd
=
self
().
fdp1
.
loadRelaxed
() - 1;
126
if
(
fd
>= 0)
127
qt_safe_close
(
fd
);
128
}
129
130
constexpr
SystemGenerator
() :
fdp1
Q_BASIC_ATOMIC_INITIALIZER
(0) {}
131
132
qsizetype
fillBuffer
(
void
*
buffer
,
qsizetype
count
)
133
{
134
int
fd
=
openDevice
();
135
if
(
Q_UNLIKELY
(
fd
< 0))
136
return
0;
137
138
qsizetype
total
= 0;
139
while
(
total
!=
count
) {
140
const
ssize_t
n
= ::
read
(
fd
,
reinterpret_cast
<
uchar
*>(
buffer
) +
total
,
count
-
total
);
141
if
(
n
> 0)
142
total
+=
n
;
143
else
if
(
n
< 0 &&
errno
==
EINTR
)
144
continue
;
145
else
146
break
;
// EOF and other errors
147
}
148
149
return
total
;
150
}
151
152
#
elif
defined
(
Q_OS_WIN
)
153
static
qsizetype
fillBuffer
(
void
*
buffer
,
qsizetype
count
)
noexcept
154
{
155
auto
RtlGenRandom
=
SystemFunction036
;
156
return
RtlGenRandom
(
buffer
,
ULONG
(
count
)) ?
count
: 0;
157
}
158
#
endif
// Q_OS_WIN
159
160
static
SystemGenerator
&
self
();
161
typedef
quint32
result_type
;
162
void
generate
(quint32 *begin, quint32 *end)
noexcept
(
FillBufferNoexcept
);
163
164
// For std::mersenne_twister_engine implementations that use something
165
// other than quint32 (unsigned int) to fill their buffers.
166
template
<
typename
T>
167
void
generate
(T *begin, T *end)
168
{
169
static_assert
(
sizeof
(T) >=
sizeof
(quint32));
170
if
(
sizeof
(T) ==
sizeof
(quint32)) {
171
// Microsoft Visual Studio uses unsigned long, but that's still 32-bit
172
generate(
reinterpret_cast
<quint32 *>(begin),
reinterpret_cast
<quint32 *>(end));
173
}
else
{
174
// Slow path. Fix your C++ library.
175
std
::generate(begin, end, [
this
]() {
176
quint32 datum;
177
generate(&datum, &datum + 1);
178
return
datum;
179
});
180
}
181
}
182
};
183
184
#
if
defined
(
Q_OS_WIN
)
185
static
void
fallback_update_seed(
unsigned
) {}
186
static
void
fallback_fill(quint32 *ptr, qsizetype left)
noexcept
187
{
188
// on Windows, rand_s is a high-quality random number generator
189
// and it requires no seeding
190
std::generate(ptr, ptr + left, []() {
191
unsigned
value;
192
rand_s(&value);
193
return
value;
194
});
195
}
196
#
elif
QT_CONFIG
(
getentropy
)
197
static
void
fallback_update_seed(
unsigned
) {}
198
static
void
fallback_fill(quint32 *, qsizetype)
noexcept
199
{
200
// no fallback necessary, getentropy cannot fail under normal circumstances
201
Q_UNREACHABLE();
202
}
203
#
elif
defined
(
Q_OS_BSD4
)
&&
!
defined
(
__GLIBC__
)
204
static
void
fallback_update_seed(
unsigned
) {}
205
static
void
fallback_fill(quint32 *ptr, qsizetype left)
noexcept
206
{
207
// BSDs have arc4random(4) and these work even in chroot(2)
208
arc4random_buf(ptr, left *
sizeof
(*ptr));
209
}
210
#
else
211
Q_CONSTINIT
static
QBasicAtomicInteger<
unsigned
> seed = Q_BASIC_ATOMIC_INITIALIZER(0U);
212
static
void
fallback_update_seed
(
unsigned
value)
213
{
214
// Update the seed to be used for the fallback mechanism, if we need to.
215
// We can't use QtPrivate::QHashCombine here because that is not an atomic
216
// operation. A simple XOR will have to do then.
217
seed.fetchAndXorRelaxed(value);
218
}
219
220
#
if
!
QT_CONFIG
(
randomgenerator_disable_fallback
)
221
Q_CONSTINIT
static
std::once_flag fallbackFillWarningFlag;
222
#
endif
223
224
// this function is pretty big, so optimize for size
225
Q_NEVER_INLINE
226
#
if
__has_attribute
(
optimize
)
// GCC
227
__attribute__
((
optimize
(
"Os"
)))
228
#
elif
__has_attribute
(
minsize
)
// Clang
229
__attribute__
((minsize))
230
#
endif
231
static
void
fallback_fill
(quint32 *ptr, qsizetype left)
noexcept
232
{
233
#
if
QT_CONFIG
(
randomgenerator_disable_fallback
)
234
Q_UNUSED(ptr);
235
Q_UNUSED(left);
236
fprintf(stderr,
"QRandomGenerator: falling back to unsafe PRNG is explicitly "
237
"disabled in the configuration. Terminating the application.\n"
238
"Check why /dev/urandom is not available on your system or "
239
"configure Qt with FEATURE_randomgenerator_disable_fallback=OFF "
240
"to enable the fallback.\n"
);
241
fflush(stderr);
242
abort();
243
#
else
244
quint32 scratch[12];
// see element count below
245
quint32 *end = scratch;
246
247
auto
foldPointer = [](quintptr v) {
248
if
(
sizeof
(quintptr) ==
sizeof
(quint32)) {
249
// For 32-bit systems, we simply return the pointer.
250
return
quint32(v);
251
}
else
{
252
// For 64-bit systems, we try to return the variable part of the
253
// pointer. On current x86-64 and AArch64, the top 17 bits are
254
// architecturally required to be the same, but in reality the top
255
// 24 bits on Linux are likely to be the same for all processes.
256
return
quint32(v >> (32 - 24));
257
}
258
};
259
260
Q_ASSERT
(left);
261
262
std::call_once(fallbackFillWarningFlag, [left] {
263
fprintf(stderr,
264
"QRandomGenerator: falling back to unsafe PRNG to initialize %lld element(s).\n"
265
"Configure Qt with FEATURE_randomgenerator_disable_fallback=ON to forbid the "
266
"fallback and terminate the application.\n"
, qlonglong(left));
267
fflush(stderr);
268
});
269
270
*end++ = foldPointer(quintptr(&seed));
// 1: variable in this library/executable's .data
271
*end++ = foldPointer(quintptr(&scratch));
// 2: variable in the stack
272
*end++ = foldPointer(quintptr(&errno));
// 3: veriable either in libc or thread-specific
273
*end++ = foldPointer(quintptr(
reinterpret_cast
<
void
*>(strerror)));
// 4: function in libc (and unlikely to be a macro)
274
275
#
ifndef
QT_BOOTSTRAPPED
276
quint64 nsecs = QDeadlineTimer::current(Qt::PreciseTimer).deadline();
277
*end++ = quint32(nsecs);
// 5
278
#
endif
279
280
if
(quint32 v = seed.loadRelaxed())
281
*end++ = v;
// 6
282
283
#
if
QT_CONFIG
(
getauxval
)
284
// works on Linux -- all modern libc have getauxval
285
#
ifdef
AT_RANDOM
286
// ELF's auxv AT_RANDOM has 16 random bytes
287
// (other ELF-based systems don't seem to have AT_RANDOM)
288
ulong auxvSeed = getauxval(AT_RANDOM);
289
if
(auxvSeed) {
290
memcpy(end,
reinterpret_cast
<
void
*>(auxvSeed), 16);
291
end += 4;
// 7 to 10
292
}
293
#
endif
294
295
// Both AT_BASE and AT_SYSINFO_EHDR have some randomness in them due to the
296
// system's ASLR, even if many bits are the same. They also have randomness
297
// between them.
298
#
ifdef
AT_BASE
299
// present at least on the BSDs too, indicates the address of the loader
300
ulong base = getauxval(AT_BASE);
301
if
(base)
302
*end++ = foldPointer(base);
// 11
303
#
endif
304
#
ifdef
AT_SYSINFO_EHDR
305
// seems to be Linux-only, indicates the global page of the sysinfo
306
ulong sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
307
if
(sysinfo_ehdr)
308
*end++ = foldPointer(sysinfo_ehdr);
// 12
309
#
endif
310
#
endif
311
312
Q_ASSERT
(end <=
std
::end(scratch));
313
314
// this is highly inefficient, we should save the generator across calls...
315
std
::seed_seq sseq(scratch, end);
316
std
::mt19937 generator(sseq);
317
std
::generate(ptr, ptr + left, generator);
318
319
fallback_update_seed(*ptr);
320
#
endif
// QT_CONFIG(randomgenerator_disable_fallback)
321
}
322
#
endif
323
324
Q_NEVER_INLINE
void
QRandomGenerator::
SystemGenerator
::
generate
(quint32 *begin, quint32 *end)
325
noexcept
(
FillBufferNoexcept
)
326
{
327
quint32 *buffer = begin;
328
qsizetype count = end - begin;
329
330
if
(Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) &
SetRandomData
)) {
331
uint value = uint(qt_randomdevice_control.loadAcquire()) &
RandomDataMask
;
332
std
::fill_n(buffer, count, value);
333
return
;
334
}
335
336
qsizetype filled = 0;
337
if
((uint(qt_randomdevice_control.loadAcquire()) &
SkipSystemRNG
) == 0) {
338
qsizetype bytesFilled =
339
fillBuffer(buffer + filled, (count - filled) * qsizetype(
sizeof
(*buffer)));
340
filled += bytesFilled / qsizetype(
sizeof
(*buffer));
341
}
342
if
(filled)
343
fallback_update_seed(*buffer);
344
345
if
(Q_UNLIKELY(filled != count)) {
346
// failed to fill the entire buffer, try the faillback mechanism
347
fallback_fill(buffer + filled, count - filled);
348
}
349
}
350
351
struct
QRandomGenerator::
SystemAndGlobalGenerators
352
{
353
// Construction notes:
354
// 1) The global PRNG state is in a different cacheline compared to the
355
// mutex that protects it. This avoids any false cacheline sharing of
356
// the state in case another thread tries to lock the mutex. It's not
357
// a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
358
// overhead is actually acceptable.
359
// 2) We use both alignas(T) and alignas(64) because some implementations
360
// can't align to more than a primitive type's alignment.
361
// 3) We don't store the entire system QRandomGenerator, only the space
362
// used by the QRandomGenerator::type member. This is fine because we
363
// (ab)use the common initial sequence exclusion to aliasing rules.
364
QBasicMutex
globalPRNGMutex
;
365
struct
ShortenedSystem
{ uint
type
; } system_;
366
SystemGenerator
sys
;
367
alignas
(64)
struct
{
368
alignas
(QRandomGenerator64) uchar data[
sizeof
(
QRandomGenerator64
)];
369
} global_;
370
371
constexpr
SystemAndGlobalGenerators
()
372
:
globalPRNGMutex
{}, system_{0},
sys
{},
global_
{}
373
{}
374
375
void
confirmLiteral
()
376
{
377
#
if
!
defined
(
Q_OS_INTEGRITY
)
378
// Integrity's compiler is unable to guarantee g's alignment for some reason.
379
constexpr
SystemAndGlobalGenerators
g =
{
}
;
380
Q_UNUSED(g);
381
#
endif
382
}
383
384
static
SystemAndGlobalGenerators
*
self
()
385
{
386
Q_CONSTINIT
static
SystemAndGlobalGenerators g;
387
static_assert
(
sizeof
(g) >
sizeof
(QRandomGenerator64));
388
return
&g;
389
}
390
391
static
QRandomGenerator64
*
system
()
392
{
393
// Though we never call the constructor, the system QRandomGenerator is
394
// properly initialized by the zero initialization performed in self().
395
// Though QRandomGenerator is has non-vacuous initialization, we
396
// consider it initialized because of the common initial sequence.
397
return
reinterpret_cast
<
QRandomGenerator64
*>(&
self
(
)
->system_);
398
}
399
400
static
QRandomGenerator64
*
globalNoInit
()
401
{
402
// This function returns the pointer to the global QRandomGenerator,
403
// but does not initialize it. Only call it directly if you meant to do
404
// a pointer comparison.
405
return
reinterpret_cast
<
QRandomGenerator64
*>(&
self
(
)
->global_);
406
}
407
408
static
void
securelySeed
(QRandomGenerator *rng)
409
{
410
// force reconstruction, just to be pedantic
411
new
(rng) QRandomGenerator{System{}};
412
413
rng->type =
MersenneTwister
;
414
new
(&rng->storage.engine()) RandomEngine(self()->sys);
415
}
416
417
struct
PRNGLocker
418
{
419
Q_DISABLE_COPY_MOVE
(
PRNGLocker
)
420
const
bool
locked
;
421
Q_NODISCARD_CTOR
explicit
PRNGLocker
(
const
QRandomGenerator
*
that
)
422
:
locked
(
that
==
globalNoInit
())
423
{
424
if
(
locked
)
425
self
()->
globalPRNGMutex
.
lock
();
426
}
427
~
PRNGLocker
()
428
{
429
if
(
locked
)
430
self
(
)
->globalPRNGMutex.unlock();
431
}
432
};
433
};
434
435
inline
QRandomGenerator::
SystemGenerator
&QRandomGenerator::
SystemGenerator
::
self
()
436
{
437
return
SystemAndGlobalGenerators
::
self
(
)
->
sys
;
438
}
439
440
/*!
441
\class QRandomGenerator
442
\inmodule QtCore
443
\reentrant
444
\since 5.10
445
446
\brief The QRandomGenerator class allows one to obtain random values from a
447
high-quality Random Number Generator.
448
449
QRandomGenerator may be used to generate random values from a high-quality
450
random number generator. Like the C++ random engines, QRandomGenerator can
451
be seeded with user-provided values through the constructor.
452
When seeded, the sequence of numbers generated by this
453
class is deterministic. That is to say, given the same seed data,
454
QRandomGenerator will generate the same sequence of numbers. But given
455
different seeds, the results should be considerably different.
456
457
QRandomGenerator::securelySeeded() can be used to create a QRandomGenerator
458
that is securely seeded with QRandomGenerator::system(), meaning that the
459
sequence of numbers it generates cannot be easily predicted. Additionally,
460
QRandomGenerator::global() returns a global instance of QRandomGenerator
461
that Qt will ensure to be securely seeded. This object is thread-safe, may
462
be shared for most uses, and is always seeded from
463
QRandomGenerator::system()
464
465
QRandomGenerator::system() may be used to access the system's
466
cryptographically-safe random generator. On Unix systems, it's equivalent
467
to reading from \c {/dev/urandom} or the \c {getrandom()} or \c
468
{getentropy()} system calls.
469
470
The class can generate 32-bit or 64-bit quantities, or fill an array of
471
those. The most common way of generating new values is to call the generate(),
472
generate64() or fillRange() functions. One would use it as:
473
474
\snippet code/src_corelib_global_qrandom.cpp 0
475
476
Additionally, it provides a floating-point function generateDouble() that
477
returns a number in the range [0, 1) (that is, inclusive of zero and
478
exclusive of 1). There's also a set of convenience functions that
479
facilitate obtaining a random number in a bounded, integral range.
480
481
\section1 Seeding and determinism
482
483
QRandomGenerator may be seeded with specific seed data. When that is done,
484
the numbers generated by the object will always be the same, as in the
485
following example:
486
487
\snippet code/src_corelib_global_qrandom.cpp 1
488
489
The seed data takes the form of one or more 32-bit words. The ideal seed
490
size is approximately equal to the size of the QRandomGenerator class
491
itself. Due to mixing of the seed data, QRandomGenerator cannot guarantee
492
that distinct seeds will produce different sequences.
493
494
QRandomGenerator::global(), like all generators created by
495
QRandomGenerator::securelySeeded(), is always seeded from
496
QRandomGenerator::system(), so it's not possible to make it produce
497
identical sequences.
498
499
\section1 Bulk data
500
501
When operating in deterministic mode, QRandomGenerator may be used for bulk
502
data generation. In fact, applications that do not need
503
cryptographically-secure or true random data are advised to use a regular
504
QRandomGenerator instead of QRandomGenerator::system() for their random
505
data needs.
506
507
For ease of use, QRandomGenerator provides a global object that can
508
be easily used, as in the following example:
509
510
\snippet code/src_corelib_global_qrandom.cpp 2
511
512
\section1 System-wide random number generator
513
514
QRandomGenerator::system() may be used to access the system-wide random
515
number generator, which is cryptographically-safe on all systems that Qt
516
runs on. This function will use hardware facilities to generate random
517
numbers where available. On such systems, those facilities are true Random
518
Number Generators. However, if they are true RNGs, those facilities have
519
finite entropy sources and thus may fail to produce any results if their
520
entropy pool is exhausted.
521
522
If that happens, first the operating system then QRandomGenerator will fall
523
back to Pseudo Random Number Generators of decreasing qualities (Qt's
524
fallback generator being the simplest). Whether those generators are still
525
of cryptographic quality is implementation-defined. Therefore,
526
QRandomGenerator::system() should not be used for high-frequency random
527
number generation, lest the entropy pool become empty. As a rule of thumb,
528
this class should not be called upon to generate more than a kilobyte per
529
second of random data (note: this may vary from system to system).
530
531
If an application needs true RNG data in bulk, it should use the operating
532
system facilities (such as \c{/dev/random} on Linux) directly and wait for
533
entropy to become available. If the application requires PRNG engines of
534
cryptographic quality but not of true randomness,
535
QRandomGenerator::system() may still be used (see section below).
536
537
If neither a true RNG nor a cryptographically secure PRNG (CSPRNG) are required,
538
applications should instead use PRNG engines like QRandomGenerator's
539
deterministic mode and those from the C++ Standard Library.
540
QRandomGenerator::system() can be used to seed those.
541
542
\section2 Fallback quality
543
544
QRandomGenerator::system() uses the operating system facilities to obtain
545
random numbers, which attempt to collect real entropy from the surrounding
546
environment to produce true random numbers. However, it's possible that the
547
entropy pool becomes exhausted, in which case the operating system will
548
fall back to a pseudo-random engine for a time. Under no circumstances will
549
QRandomGenerator::system() block, waiting for more entropy to be collected.
550
551
The following operating systems guarantee that the results from their
552
random-generation API will be of at least cryptographically-safe quality,
553
even if the entropy pool is exhausted: Apple OSes (Darwin), BSDs, Linux,
554
Windows. Barring a system installation problem (such as \c{/dev/urandom}
555
not being readable by the current process), QRandomGenerator::system() will
556
therefore have the same guarantees.
557
558
On other operating systems, QRandomGenerator will fall back to a PRNG of
559
good numeric distribution, but it cannot guarantee proper seeding in all
560
cases. Please consult the OS documentation for more information.
561
562
Applications that require QRandomGenerator not to fall back to
563
non-cryptographic quality generators are advised to check their operating
564
system documentation or restrict their deployment to one of the above.
565
566
Starting from Qt 6.12, QRandomGenerator prints a warning to \c stderr the
567
first time it falls back to insecure PRNG. The opt-in feature
568
\c {randomgenerator_disable_fallback} can be set during Qt build to disable
569
the insecure fallback and instead terminate the application if it tried to
570
use QRandomGenerator and CSPRNG is not available.
571
572
\section1 Reentrancy and thread-safety
573
574
QRandomGenerator is reentrant, meaning that multiple threads can operate on
575
this class at the same time, so long as they operate on different objects.
576
If multiple threads need to share one PRNG sequence, external locking by a
577
mutex is required.
578
579
The exceptions are the objects returned by QRandomGenerator::global() and
580
QRandomGenerator::system(): those objects are thread-safe and may be used
581
by any thread without external locking. Note that thread-safety does not
582
extend to copying those objects: they should always be used by reference.
583
584
\section1 Standard C++ Library compatibility
585
586
QRandomGenerator is modeled after the requirements for random number
587
engines in the C++ Standard Library and may be used in almost all contexts
588
that the Standard Library engines can. Exceptions to the requirements are
589
the following:
590
591
\list
592
\li QRandomGenerator does not support seeding from another seed
593
sequence-like class besides std::seed_seq itself;
594
\li QRandomGenerator is not comparable (but is copyable) or
595
streamable to \c{std::ostream} or from \c{std::istream}.
596
\endlist
597
598
QRandomGenerator is also compatible with the uniform distribution classes
599
\c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as
600
well as the free function \c{std::generate_canonical}. For example, the
601
following code may be used to generate a floating-point number in the range
602
[1, 2.5):
603
604
\snippet code/src_corelib_global_qrandom.cpp 3
605
606
\sa QRandomGenerator64
607
*/
608
609
/*!
610
\enum QRandomGenerator::System
611
\internal
612
*/
613
614
/*!
615
\fn QRandomGenerator::QRandomGenerator(quint32 seedValue)
616
617
Initializes this QRandomGenerator object with the value \a seedValue as
618
the seed. Two objects constructed or reseeded with the same seed value will
619
produce the same number sequence.
620
621
\sa seed(), securelySeeded()
622
*/
623
624
/*!
625
\fn template <qsizetype N> QRandomGenerator::QRandomGenerator(const quint32 (&seedBuffer)[N])
626
\overload
627
628
Initializes this QRandomGenerator object with the values found in the
629
array \a seedBuffer as the seed. Two objects constructed or reseeded with
630
the same seed value will produce the same number sequence.
631
632
\sa seed(), securelySeeded()
633
*/
634
635
/*!
636
\fn QRandomGenerator::QRandomGenerator(const quint32 *seedBuffer, qsizetype len)
637
\overload
638
639
Initializes this QRandomGenerator object with \a len values found in
640
the array \a seedBuffer as the seed. Two objects constructed or reseeded
641
with the same seed value will produce the same number sequence.
642
643
This constructor is equivalent to:
644
\snippet code/src_corelib_global_qrandom.cpp 4
645
646
\sa seed(), securelySeeded()
647
*/
648
649
/*!
650
\fn QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end)
651
\overload
652
653
Initializes this QRandomGenerator object with the values found in the range
654
from \a begin to \a end as the seed. Two objects constructed or reseeded
655
with the same seed value will produce the same number sequence.
656
657
This constructor is equivalent to:
658
\snippet code/src_corelib_global_qrandom.cpp 5
659
660
\sa seed(), securelySeeded()
661
*/
662
663
/*!
664
\fn QRandomGenerator::QRandomGenerator(std::seed_seq &sseq)
665
\overload
666
667
Initializes this QRandomGenerator object with the seed sequence \a
668
sseq as the seed. Two objects constructed or reseeded with the same seed
669
value will produce the same number sequence.
670
671
\sa seed(), securelySeeded()
672
*/
673
674
/*!
675
\fn QRandomGenerator::QRandomGenerator(const QRandomGenerator &other)
676
677
Creates a copy of the generator state in the \a other object. If \a other is
678
QRandomGenerator::system() or a copy of that, this object will also read
679
from the operating system random-generating facilities. In that case, the
680
sequences generated by the two objects will be different.
681
682
In all other cases, the new QRandomGenerator object will start at the same
683
position in the deterministic sequence as the \a other object was. Both
684
objects will generate the same sequence from this point on.
685
686
For that reason, it is not advisable to create a copy of
687
QRandomGenerator::global(). If one needs an exclusive deterministic
688
generator, consider instead using securelySeeded() to obtain a new object
689
that shares no relationship with the QRandomGenerator::global().
690
*/
691
692
/*!
693
\fn bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
694
\relates QRandomGenerator
695
696
Returns true if the two engines \a rng1 and \a rng2 are at the same
697
state or if they are both reading from the operating system facilities,
698
false otherwise.
699
*/
700
701
/*!
702
\fn bool QRandomGenerator::operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
703
704
Returns \c true if the two engines \a rng1 and \a rng2 are at
705
different states or if one of them is reading from the operating system
706
facilities and the other is not, \c false otherwise.
707
*/
708
709
/*!
710
\typedef QRandomGenerator::result_type
711
712
A typedef to the type that operator() returns. That is, quint32.
713
714
\sa operator()
715
*/
716
717
/*!
718
\fn result_type QRandomGenerator::operator()()
719
720
Generates a 32-bit random quantity and returns it.
721
722
\sa generate(), generate64()
723
*/
724
725
/*!
726
\fn quint32 QRandomGenerator::generate()
727
728
Generates a 32-bit random quantity and returns it.
729
730
\sa {QRandomGenerator::operator()}{operator()()}, generate64()
731
*/
732
733
/*!
734
\fn quint64 QRandomGenerator::generate64()
735
736
Generates a 64-bit random quantity and returns it.
737
738
\sa {QRandomGenerator::operator()}{operator()()}, generate()
739
*/
740
741
/*!
742
\fn result_type QRandomGenerator::min()
743
744
Returns the minimum value that QRandomGenerator may ever generate. That is, 0.
745
746
\sa max()
747
*/
748
749
/*!
750
\fn result_type QRandomGenerator::max()
751
752
Returns the maximum value that QRandomGenerator may ever generate. That is,
753
\c {std::numeric_limits<result_type>::max()}.
754
755
\sa min()
756
*/
757
758
/*!
759
\fn void QRandomGenerator::seed(quint32 seed)
760
761
Reseeds this object using the value \a seed as the seed.
762
*/
763
764
/*!
765
\fn void QRandomGenerator::seed(std::seed_seq &seed)
766
\overload
767
768
Reseeds this object using the seed sequence \a seed as the seed.
769
*/
770
771
/*!
772
\fn void QRandomGenerator::discard(unsigned long long z)
773
774
Discards the next \a z entries from the sequence. This method is equivalent
775
to calling generate() \a z times and discarding the result, as in:
776
777
\snippet code/src_corelib_global_qrandom.cpp 6
778
*/
779
780
/*!
781
\fn template <typename ForwardIterator> void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end)
782
783
Generates 32-bit quantities and stores them in the range between \a begin
784
and \a end. This function is equivalent to (and is implemented as):
785
786
\snippet code/src_corelib_global_qrandom.cpp 7
787
788
This function complies with the requirements for the function
789
\l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq/generate}{\c std::seed_seq::generate},
790
which requires unsigned 32-bit integer values.
791
792
Note that if the [begin, end) range refers to an area that can store more
793
than 32 bits per element, the elements will still be initialized with only
794
32 bits of data. Any other bits will be zero. To fill the range with 64 bit
795
quantities, one can write:
796
797
\snippet code/src_corelib_global_qrandom.cpp 8
798
799
If the range refers to contiguous memory (such as an array or the data from
800
a QList), the fillRange() function may be used too.
801
802
\sa fillRange()
803
*/
804
805
/*!
806
\fn void QRandomGenerator::generate(quint32 *begin, quint32 *end)
807
\overload
808
\internal
809
810
Same as the other overload, but more efficiently fills \a begin to \a end.
811
*/
812
813
/*!
814
\fn template <typename UInt, QRandomGenerator::IfValidUInt<UInt> = true> void QRandomGenerator::fillRange(UInt *buffer, qsizetype count)
815
816
Generates \a count 32- or 64-bit quantities (depending on the type \c UInt)
817
and stores them in the buffer pointed by \a buffer. This is the most
818
efficient way to obtain more than one quantity at a time, as it reduces the
819
number of calls into the Random Number Generator source.
820
821
For example, to fill a list of 16 entries with random values, one may
822
write:
823
824
\snippet code/src_corelib_global_qrandom.cpp 9
825
826
\sa generate()
827
*/
828
829
/*!
830
\fn template <typename UInt, size_t N, QRandomGenerator::IfValidUInt<UInt> = true> void QRandomGenerator::fillRange(UInt (&buffer)[N])
831
832
Generates \a N 32-bit or 64-bit quantities (depending on the type \c UInt) and
833
stores them in the \a buffer array. This is the most efficient way to
834
obtain more than one quantity at a time, as it reduces the number of calls
835
into the Random Number Generator source.
836
837
For example, to fill generate two 32-bit quantities, one may write:
838
839
\snippet code/src_corelib_global_qrandom.cpp 10
840
841
It would have also been possible to make one call to generate64() and then split
842
the two halves of the 64-bit value.
843
844
\sa generate()
845
*/
846
847
/*!
848
\fn qreal QRandomGenerator::generateDouble()
849
850
Generates one random qreal in the canonical range [0, 1) (that is,
851
inclusive of zero and exclusive of 1).
852
853
This function is equivalent to:
854
\snippet code/src_corelib_global_qrandom.cpp 11
855
856
The same may also be obtained by using
857
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{\c std::uniform_real_distribution}
858
with parameters 0 and 1.
859
860
\sa generate(), generate64(), bounded()
861
*/
862
863
/*!
864
\fn double QRandomGenerator::bounded(double highest)
865
866
Generates one random double in the range between 0 (inclusive) and \a
867
highest (exclusive). This function is equivalent to and is implemented as:
868
869
\snippet code/src_corelib_global_qrandom.cpp 12
870
871
If the \a highest parameter is negative, the result will be negative too;
872
if it is infinite or NaN, the result will be infinite or NaN too (that is,
873
not random).
874
875
\sa generateDouble(), bounded(quint64)
876
*/
877
878
/*!
879
\fn quint32 QRandomGenerator::bounded(quint32 highest)
880
\overload
881
882
Generates one random 32-bit quantity in the range between 0 (inclusive) and
883
\a highest (exclusive). The same result may also be obtained by using
884
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution}
885
with parameters 0 and \c{highest - 1}. That class can also be used to obtain
886
quantities larger than 32 bits; for 64 bits, the 64-bit bounded() overload
887
can be used too.
888
889
For example, to obtain a value between 0 and 255 (inclusive), one would write:
890
891
\snippet code/src_corelib_global_qrandom.cpp 13
892
893
Naturally, the same could also be obtained by masking the result of generate()
894
to only the lower 8 bits. Either solution is as efficient.
895
896
Note that this function cannot be used to obtain values in the full 32-bit
897
range of quint32. Instead, use generate().
898
899
\sa generate(), generate64(), generateDouble()
900
*/
901
902
/*!
903
\fn int QRandomGenerator::bounded(int highest)
904
\overload
905
906
Generates one random 32-bit quantity in the range between 0 (inclusive) and
907
\a highest (exclusive). \a highest must be positive.
908
909
Note that this function cannot be used to obtain values in the full 32-bit
910
range of int. Instead, use generate() and cast to int.
911
912
\sa generate(), generate64(), generateDouble()
913
*/
914
915
/*!
916
\fn quint64 QRandomGenerator::bounded(quint64 highest)
917
\overload
918
919
Generates one random 64-bit quantity in the range between 0 (inclusive) and
920
\a highest (exclusive). The same result may also be obtained by using
921
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
922
with parameters 0 and \c{highest - 1}.
923
924
Note that this function cannot be used to obtain values in the full 64-bit
925
range of \c{quint64}. Instead, use generate64().
926
927
\note This function is implemented as a loop, which depends on the random
928
value obtained. On the long run, on average it should loop just under 2
929
times, but if the random generator is defective, this function may take
930
considerably longer to execute.
931
932
\sa generate(), generate64(), generateDouble()
933
*/
934
935
/*!
936
\fn qint64 QRandomGenerator::bounded(qint64 highest)
937
\overload
938
939
Generates one random 64-bit quantity in the range between 0 (inclusive) and
940
\a highest (exclusive). \a highest must be positive.
941
942
Note that this function cannot be used to obtain values in the full 64-bit
943
range of \c{qint64}. Instead, use generate64() and cast to qint64 or instead
944
use the unsigned version of this function.
945
946
\note This function is implemented as a loop, which depends on the random
947
value obtained. On the long run, on average it should loop just under 2
948
times, but if the random generator is defective, this function may take
949
considerably longer to execute.
950
951
\sa generate(), generate64(), generateDouble()
952
*/
953
954
/*!
955
\fn quint32 QRandomGenerator::bounded(quint32 lowest, quint32 highest)
956
\overload
957
958
Generates one random 32-bit quantity in the range between \a lowest
959
(inclusive) and \a highest (exclusive). The \a highest parameter must be
960
greater than \a lowest.
961
962
The same result may also be obtained by using
963
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution}
964
with parameters \a lowest and \c{\a highest - 1}. That class can also be used to
965
obtain quantities larger than 32 bits.
966
967
For example, to obtain a value between 1000 (incl.) and 2000 (excl.), one
968
would write:
969
970
\snippet code/src_corelib_global_qrandom.cpp 14
971
972
Note that this function cannot be used to obtain values in the full 32-bit
973
range of quint32. Instead, use generate().
974
975
\sa generate(), generate64(), generateDouble()
976
*/
977
978
/*!
979
\fn int QRandomGenerator::bounded(int lowest, int highest)
980
\overload
981
982
Generates one random 32-bit quantity in the range between \a lowest
983
(inclusive) and \a highest (exclusive), both of which may be negative, but
984
\a highest must be greater than \a lowest.
985
986
Note that this function cannot be used to obtain values in the full 32-bit
987
range of int. Instead, use generate() and cast to int.
988
989
\sa generate(), generate64(), generateDouble()
990
*/
991
992
/*!
993
\fn quint64 QRandomGenerator::bounded(quint64 lowest, quint64 highest)
994
\overload
995
996
Generates one random 64-bit quantity in the range between \a lowest
997
(inclusive) and \a highest (exclusive). The \a highest parameter must be
998
greater than \a lowest.
999
1000
The same result may also be obtained by using
1001
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
1002
with parameters \a lowest and \c{\a highest - 1}.
1003
1004
Note that this function cannot be used to obtain values in the full 64-bit
1005
range of \c{quint64}. Instead, use generate64().
1006
1007
\note This function is implemented as a loop, which depends on the random
1008
value obtained. On the long run, on average it should loop just under 2
1009
times, but if the random generator is defective, this function may take
1010
considerably longer to execute.
1011
1012
\sa generate(), generate64(), generateDouble()
1013
*/
1014
1015
/*!
1016
\fn qint64 QRandomGenerator::bounded(qint64 lowest, qint64 highest)
1017
\overload
1018
1019
Generates one random 64-bit quantity in the range between \a lowest
1020
(inclusive) and \a highest (exclusive), both of which may be negative, but
1021
\a highest must be greater than \a lowest.
1022
1023
Note that this function cannot be used to obtain values in the full 64-bit
1024
range of \c{qint64}. Instead, use generate64() and cast to qint64.
1025
1026
\note This function is implemented as a loop, which depends on the random
1027
value obtained. On the long run, on average it should loop just under 2
1028
times, but if the random generator is defective, this function may take
1029
considerably longer to execute.
1030
1031
\sa generate(), generate64(), generateDouble()
1032
*/
1033
1034
/*!
1035
\fn qint64 QRandomGenerator::bounded(int lowest, qint64 highest)
1036
\fn qint64 QRandomGenerator::bounded(qint64 lowest, int highest)
1037
\fn quint64 QRandomGenerator::bounded(unsigned lowest, quint64 highest)
1038
\fn quint64 QRandomGenerator::bounded(quint64 lowest, unsigned highest)
1039
\overload
1040
1041
This function exists to help with overload resolution when the types of the
1042
parameters don't exactly match. They will promote the smaller type to the
1043
type of the larger one and call the correct overload.
1044
*/
1045
1046
/*!
1047
\fn QRandomGenerator *QRandomGenerator::system()
1048
\threadsafe
1049
1050
Returns a pointer to a shared QRandomGenerator that always uses the
1051
facilities provided by the operating system to generate random numbers. The
1052
system facilities are considered to be cryptographically safe on at least
1053
the following operating systems: Apple OSes (Darwin), BSDs, Linux, Windows.
1054
That may also be the case on other operating systems.
1055
1056
They are also possibly backed by a true hardware random number generator.
1057
For that reason, the QRandomGenerator returned by this function should not
1058
be used for bulk data generation. Instead, use it to seed QRandomGenerator
1059
or a random engine from the <random> header.
1060
1061
The object returned by this function is thread-safe and may be used in any
1062
thread without locks. It may also be copied and the resulting
1063
QRandomGenerator will also access the operating system facilities, but they
1064
will not generate the same sequence.
1065
1066
\sa securelySeeded(), global()
1067
*/
1068
1069
/*!
1070
\fn QRandomGenerator *QRandomGenerator::global()
1071
\threadsafe
1072
1073
Returns a pointer to a shared QRandomGenerator that was seeded using
1074
securelySeeded(). This function should be used to create random data
1075
without the expensive creation of a securely-seeded QRandomGenerator
1076
for a specific use or storing the rather large QRandomGenerator object.
1077
1078
For example, the following creates a random RGB color:
1079
1080
\snippet code/src_corelib_global_qrandom.cpp 15
1081
1082
Accesses to this object are thread-safe and it may therefore be used in any
1083
thread without locks. The object may also be copied and the sequence
1084
produced by the copy will be the same as the shared object will produce.
1085
Note, however, that if there are other threads accessing the global object,
1086
those threads may obtain samples at unpredictable intervals.
1087
1088
\sa securelySeeded(), system()
1089
*/
1090
1091
/*!
1092
\fn QRandomGenerator QRandomGenerator::securelySeeded()
1093
1094
Returns a new QRandomGenerator object that was securely seeded with
1095
QRandomGenerator::system(). This function will obtain the ideal seed size
1096
for the algorithm that QRandomGenerator uses and is therefore the
1097
recommended way for creating a new QRandomGenerator object that will be
1098
kept for some time.
1099
1100
Given the amount of data required to securely seed the deterministic
1101
engine, this function is somewhat expensive and should not be used for
1102
short-term uses of QRandomGenerator (using it to generate fewer than 2600
1103
bytes of random data is effectively a waste of resources). If the use
1104
doesn't require that much data, consider using QRandomGenerator::global()
1105
and not storing a QRandomGenerator object instead.
1106
1107
\sa global(), system()
1108
*/
1109
1110
/*!
1111
\class QRandomGenerator64
1112
\inmodule QtCore
1113
\since 5.10
1114
1115
\brief The QRandomGenerator64 class allows one to obtain 64-bit random values
1116
from a high-quality, seed-less Random Number Generator.
1117
1118
QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
1119
QRandomGenerator::generate64() function the default for operator()(), instead of the
1120
function that returns 32-bit quantities. This class is intended to be used
1121
in conjunction with Standard Library algorithms that need 64-bit quantities
1122
instead of 32-bit ones.
1123
1124
In all other aspects, the class is the same. Please refer to
1125
QRandomGenerator's documentation for more information.
1126
1127
\sa QRandomGenerator
1128
*/
1129
1130
/*!
1131
\typedef QRandomGenerator64::result_type
1132
1133
A typedef to the type that operator() returns. That is, quint64.
1134
1135
\sa operator()
1136
*/
1137
1138
/*!
1139
\fn quint64 QRandomGenerator64::generate()
1140
1141
Generates one 64-bit random value and returns it.
1142
1143
Note about casting to a signed integer: all bits returned by this function
1144
are random, so there's a 50% chance that the most significant bit will be
1145
set. If you wish to cast the returned value to qint64 and keep it positive,
1146
you should mask the sign bit off:
1147
1148
\snippet code/src_corelib_global_qrandom.cpp 16
1149
1150
\sa QRandomGenerator, QRandomGenerator::generate64()
1151
*/
1152
1153
/*!
1154
\fn result_type QRandomGenerator64::operator()()
1155
1156
Generates a 64-bit random quantity and returns it.
1157
1158
\sa QRandomGenerator::generate(), QRandomGenerator::generate64()
1159
*/
1160
1161
constexpr
QRandomGenerator::Storage::Storage()
1162
: dummy(0)
1163
{
1164
// nothing
1165
}
1166
1167
inline
QRandomGenerator64
::QRandomGenerator64(System s)
1168
: QRandomGenerator(s)
1169
{
1170
}
1171
1172
QRandomGenerator64
*
QRandomGenerator64
::system()
1173
{
1174
auto
self =
SystemAndGlobalGenerators
::
system
(
)
;
1175
Q_ASSERT
(self->type ==
SystemRNG
);
1176
return
self;
1177
}
1178
1179
QRandomGenerator64
*
QRandomGenerator64
::global()
1180
{
1181
auto
self =
SystemAndGlobalGenerators
::
globalNoInit
(
)
;
1182
1183
// Yes, this is a double-checked lock.
1184
// We can return even if the type is not completely initialized yet:
1185
// any thread trying to actually use the contents of the random engine
1186
// will necessarily wait on the lock.
1187
if
(Q_LIKELY(self->type !=
SystemRNG
))
1188
return
self;
1189
1190
SystemAndGlobalGenerators
::
PRNGLocker
locker(self);
1191
if
(self->type ==
SystemRNG
)
1192
SystemAndGlobalGenerators
::
securelySeed
(self);
1193
1194
return
self;
1195
}
1196
1197
QRandomGenerator64
QRandomGenerator64
::securelySeeded()
1198
{
1199
QRandomGenerator64
result(System{});
1200
SystemAndGlobalGenerators
::
securelySeed
(&result);
1201
return
result;
1202
}
1203
1204
/*!
1205
\internal
1206
*/
1207
inline
QRandomGenerator::QRandomGenerator(System)
1208
: type(
SystemRNG
)
1209
{
1210
// don't touch storage
1211
}
1212
1213
QRandomGenerator::QRandomGenerator(
const
QRandomGenerator &other)
1214
: type(other.type)
1215
{
1216
Q_ASSERT
(
this
!= system());
1217
Q_ASSERT
(
this
!=
SystemAndGlobalGenerators
::
globalNoInit
(
)
);
1218
1219
if
(type !=
SystemRNG
) {
1220
SystemAndGlobalGenerators
::
PRNGLocker
lock(&other);
1221
storage.engine() = other.storage.engine();
1222
}
1223
}
1224
1225
QRandomGenerator &QRandomGenerator::operator=(
const
QRandomGenerator &other)
1226
{
1227
if
(Q_UNLIKELY(
this
== system()) || Q_UNLIKELY(
this
==
SystemAndGlobalGenerators
::
globalNoInit
(
)
))
1228
qFatal(
"Attempted to overwrite a QRandomGenerator to system() or global()."
);
1229
1230
if
((type = other.type) !=
SystemRNG
) {
1231
SystemAndGlobalGenerators
::
PRNGLocker
lock(&other);
1232
storage.engine() = other.storage.engine();
1233
}
1234
return
*
this
;
1235
}
1236
1237
QRandomGenerator::QRandomGenerator(
std
::seed_seq &sseq)
noexcept
1238
: type(
MersenneTwister
)
1239
{
1240
Q_ASSERT
(
this
!= system());
1241
Q_ASSERT
(
this
!=
SystemAndGlobalGenerators
::
globalNoInit
(
)
);
1242
1243
new
(&storage.engine()) RandomEngine(sseq);
1244
}
1245
1246
QRandomGenerator::QRandomGenerator(
const
quint32 *begin,
const
quint32 *end)
1247
: type(
MersenneTwister
)
1248
{
1249
Q_ASSERT
(
this
!= system());
1250
Q_ASSERT
(
this
!=
SystemAndGlobalGenerators
::
globalNoInit
(
)
);
1251
1252
std
::seed_seq s(begin, end);
1253
new
(&storage.engine()) RandomEngine(s);
1254
}
1255
1256
void
QRandomGenerator::discard(
unsigned
long
long
z)
1257
{
1258
if
(Q_UNLIKELY(type ==
SystemRNG
))
1259
return
;
1260
1261
SystemAndGlobalGenerators
::
PRNGLocker
lock(
this
);
1262
storage.engine().discard(z);
1263
}
1264
1265
bool
operator
==(
const
QRandomGenerator &rng1,
const
QRandomGenerator &rng2)
1266
{
1267
if
(rng1.type != rng2.type)
1268
return
false
;
1269
if
(rng1.type ==
SystemRNG
)
1270
return
true
;
1271
1272
// Lock global() if either is it (otherwise this locking is a no-op)
1273
using
PRNGLocker = QRandomGenerator::
SystemAndGlobalGenerators
::
PRNGLocker
;
1274
PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2);
1275
return
rng1.storage.engine() == rng2.storage.engine();
1276
}
1277
1278
/*!
1279
\internal
1280
1281
Fills the range pointed by \a buffer with \a count 32-bit random values.
1282
The buffer must be correctly aligned.
1283
1284
Returns the value of the first two 32-bit entries as a \c{quint64}.
1285
*/
1286
quint64 QRandomGenerator::_fillRange(
void
*buffer, qptrdiff count)
1287
{
1288
// Verify that the pointers are properly aligned for 32-bit
1289
Q_ASSERT
(quintptr(buffer) %
sizeof
(quint32) == 0);
1290
Q_ASSERT
(count >= 0);
1291
Q_ASSERT
(buffer || count <= 2);
1292
1293
quint64 dummy;
1294
quint32 *begin =
static_cast
<quint32 *>(buffer ? buffer : &dummy);
1295
quint32 *end = begin + count;
1296
1297
if
(type ==
SystemRNG
|| Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (
UseSystemRNG
|
SetRandomData
))) {
1298
SystemGenerator
::
self
(
)
.generate(begin, end);
1299
}
else
{
1300
SystemAndGlobalGenerators
::
PRNGLocker
lock(
this
);
1301
std
::generate(begin, end, [
this
]() {
return
storage.engine()(); });
1302
}
1303
1304
if
(end - begin == 1)
1305
return
*begin;
1306
return
begin[0] | (quint64(begin[1]) << 32);
1307
}
1308
1309
// helper function to call fillBuffer, since we need something to be
1310
// argument-dependent
1311
template
<
typename
Generator,
typename
FillBufferType,
typename
T>
1312
static
qsizetype
callFillBuffer
(FillBufferType f, T *v)
1313
{
1314
if
constexpr
(
std
::is_member_function_pointer_v<FillBufferType>) {
1315
// member function, need an object
1316
return
(Generator::self().*f)(v,
sizeof
(*v));
1317
}
else
{
1318
// static, call directly
1319
return
f(v,
sizeof
(*v));
1320
}
1321
}
1322
1323
/*!
1324
\internal
1325
1326
Returns an initial random value (useful for QHash's global seed). This
1327
function attempts to use OS-provided random values to avoid initializing
1328
QRandomGenerator::system() and qsimd.cpp.
1329
1330
Note: on some systems, this functionn may rerturn the same value every time
1331
it is called.
1332
*/
1333
QRandomGenerator::InitialRandomData
qt_initial_random_value
()
noexcept
1334
{
1335
#
if
QT_CONFIG
(
getauxval
)
&&
defined
(
AT_RANDOM
)
1336
auto
at_random_ptr =
reinterpret_cast
<size_t *>(getauxval(AT_RANDOM));
1337
if
(at_random_ptr)
1338
return
qFromUnaligned<QRandomGenerator::InitialRandomData>(at_random_ptr);
1339
#
endif
1340
1341
// bypass the hardware RNG, which would mean initializing qsimd.cpp
1342
1343
QRandomGenerator::InitialRandomData v;
1344
for
(
int
attempts = 16; attempts; --attempts) {
1345
using
Generator = QRandomGenerator::
SystemGenerator
;
1346
auto
fillBuffer = &Generator::fillBuffer;
1347
if
(callFillBuffer<Generator>(fillBuffer, &v) !=
sizeof
(v))
1348
continue
;
1349
1350
return
v;
1351
}
1352
1353
quint32 data[
sizeof
(v) /
sizeof
(quint32)];
1354
fallback_fill(data,
std
::size(data));
1355
memcpy(v.data, data,
sizeof
(v.data));
1356
return
v;
1357
}
1358
1359
QT_END_NAMESPACE
QRandomGenerator64
\inmodule QtCore
Definition
qrandom.h:212
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
assert
#define assert
Definition
qcborcommon_p.h:29
__has_attribute
#define __has_attribute(x)
Definition
qcompilerdetection.h:450
QBasicMutex
QMutex QBasicMutex
Definition
qmutex.h:361
callFillBuffer
static qsizetype callFillBuffer(FillBufferType f, T *v)
Definition
qrandom.cpp:1312
fallback_fill
static Q_NEVER_INLINE void fallback_fill(quint32 *ptr, qsizetype left) noexcept
Definition
qrandom.cpp:231
fallback_update_seed
static void fallback_update_seed(unsigned value)
Definition
qrandom.cpp:212
operator==
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition
qrandom.cpp:1265
Q_ASSERT
#define Q_ASSERT(cond)
Definition
qrandom.cpp:52
qt_initial_random_value
QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
Definition
qrandom.cpp:1333
MersenneTwister
@ MersenneTwister
Definition
qrandom_p.h:36
SystemRNG
@ SystemRNG
Definition
qrandom_p.h:35
UseSystemRNG
@ UseSystemRNG
Definition
qrandom_p.h:26
SkipSystemRNG
@ SkipSystemRNG
Definition
qrandom_p.h:27
SetRandomData
@ SetRandomData
Definition
qrandom_p.h:28
RandomDataMask
@ RandomDataMask
Definition
qrandom_p.h:31
QRandomGenerator::SystemAndGlobalGenerators::PRNGLocker
Definition
qrandom.cpp:418
QRandomGenerator::SystemAndGlobalGenerators::PRNGLocker::~PRNGLocker
~PRNGLocker()
Definition
qrandom.cpp:427
QRandomGenerator::SystemAndGlobalGenerators::PRNGLocker::locked
const bool locked
Definition
qrandom.cpp:420
QRandomGenerator::SystemAndGlobalGenerators::ShortenedSystem
Definition
qrandom.cpp:365
QRandomGenerator::SystemAndGlobalGenerators::ShortenedSystem::type
uint type
Definition
qrandom.cpp:365
QRandomGenerator::SystemAndGlobalGenerators
Definition
qrandom.cpp:352
QRandomGenerator::SystemAndGlobalGenerators::confirmLiteral
void confirmLiteral()
Definition
qrandom.cpp:375
QRandomGenerator::SystemAndGlobalGenerators::sys
SystemGenerator sys
Definition
qrandom.cpp:366
QRandomGenerator::SystemAndGlobalGenerators::SystemAndGlobalGenerators
constexpr SystemAndGlobalGenerators()
Definition
qrandom.cpp:371
QRandomGenerator::SystemAndGlobalGenerators::system
static QRandomGenerator64 * system()
Definition
qrandom.cpp:391
QRandomGenerator::SystemAndGlobalGenerators::securelySeed
static void securelySeed(QRandomGenerator *rng)
Definition
qrandom.cpp:408
QRandomGenerator::SystemAndGlobalGenerators::globalPRNGMutex
QBasicMutex globalPRNGMutex
Definition
qrandom.cpp:364
QRandomGenerator::SystemAndGlobalGenerators::self
static SystemAndGlobalGenerators * self()
Definition
qrandom.cpp:384
QRandomGenerator::SystemAndGlobalGenerators::globalNoInit
static QRandomGenerator64 * globalNoInit()
Definition
qrandom.cpp:400
QRandomGenerator::SystemGenerator
Definition
qrandom.cpp:71
QRandomGenerator::SystemGenerator::result_type
quint32 result_type
Definition
qrandom.cpp:161
QRandomGenerator::SystemGenerator::generate
void generate(quint32 *begin, quint32 *end) noexcept(FillBufferNoexcept)
Definition
qrandom.cpp:324
QRandomGenerator::SystemGenerator::self
static SystemGenerator & self()
Definition
qrandom.cpp:435
QRandomGenerator::SystemGenerator::generate
void generate(T *begin, T *end)
Definition
qrandom.cpp:167
qtbase
src
corelib
global
qrandom.cpp
Generated on
for Qt by
1.18.0