mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-31 16:24:48 +02:00
Merge bitcoin/bitcoin#29625: Several randomness improvements
ce8094246erandom: replace construct/assign with explicit Reseed() (Pieter Wuille)2ae392d561random: use LogError for init failure (Pieter Wuille)97e16f5704tests: make fuzz tests (mostly) deterministic with fixed seed (Pieter Wuille)2c91330dd6random: cleanup order, comments, static (Pieter Wuille)8e31cf9c9bnet, net_processing: use existing RNG objects more (Pieter Wuille)d5fcbe966brandom: improve precision of MakeExponentiallyDistributed (Pieter Wuille)cfb0dfe2cfrandom: convert GetExponentialRand into rand_exp_duration (Pieter Wuille)4eaa239dc3random: convert GetRand{Micros,Millis} into randrange (Pieter Wuille)82de1b80d9net: use GetRandMicros for cache expiration (Pieter Wuille)ddc184d999random: get rid of GetRand by inlining (Pieter Wuille)e2d1f84858random: make GetRand() support entire range (incl. max) (Pieter Wuille)810cdf6b4etests: overhaul deterministic test randomness (Pieter Wuille)6cfdc5b104random: convert XoRoShiRo128PlusPlus into full RNG (Pieter Wuille)8cc2f45065random: move XoRoShiRo128PlusPlus into random module (Pieter Wuille)8f5ac0d0b6xoroshiro128plusplus: drop comment about nonexisting copy() (Pieter Wuille)8924f5120frandom: modernize XoRoShiRo128PlusPlus a bit (Pieter Wuille)ddb7d26cfdrandom: add RandomMixin::randbits with compile-known bits (Pieter Wuille)21ce9d8658random: Improve RandomMixin::randbits (Pieter Wuille)9b14d3d2darandom: refactor: move rand* utilities to RandomMixin (Pieter Wuille)40dd86fc3brandom: use BasicByte concept in randbytes (Pieter Wuille)27cefc7fd6random: add a few noexcepts to FastRandomContext (Pieter Wuille)b3b382dde2random: move rand256() and randbytes() to .h file (Pieter Wuille)493a2e024erandom: write rand256() in function of fillrand() (Pieter Wuille) Pull request description: This PR contains a number of vaguely-related improvements to the random module. The specific changes and more detailed rationale is in the commit messages, but the highlights are: * `XoRoShiRo128PlusPlus` (previously a test-only RNG) moves to random.h and becomes `InsecureRandomContext`, which is even faster than `FastRandomContext` but non-cryptographic. It also gets all helper randomness functions (`randrange`, `fillrand`, ...), making it a lot more succinct to use. * During tests, **all** randomness is made deterministic (except for `GetStrongRandBytes`) but non-repeating (like `GetRand()` used to be when `g_mock_deterministic_tests` was used), either fixed, or from a random seed (overridden by env var). * Several infrequently used top-level functions (`GetRandMillis`, `GetRandMicros`, `GetExponentialRand`) are converted into member functions of `FastRandomContext` (and `InsecureRandomContext`). * `GetRand<T>()` (without argument) can now return the maximum value of the type (previously e.g. `GetRand<uint32_t>()` would never return 0xffffffff). ACKs for top commit: achow101: ACKce8094246emaflcko: re-ACKce8094246e🐈 hodlinator: ACKce8094246edergoegge: utACKce8094246eTree-SHA512: 79bc0cbafaf27e95012c1ce2947a8ca6f9a3c78af5f1f16e69354b6fc9b987a28858adf4cd356dc5baf21163e9af8dcc24e70f8d7173be870e8a3ddcdd47c02c
This commit is contained in:
@@ -124,7 +124,7 @@ public:
|
||||
explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider)
|
||||
: AddrMan(netgroupman, /*deterministic=*/true, GetCheckRatio())
|
||||
{
|
||||
WITH_LOCK(m_impl->cs, m_impl->insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
|
||||
WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#include <bip324.h>
|
||||
#include <chainparams.h>
|
||||
#include <random.h>
|
||||
#include <span.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@@ -56,7 +56,7 @@ FUZZ_TARGET(bip324_cipher_roundtrip, .init=Initialize)
|
||||
// (potentially buggy) edge cases triggered by specific values of contents/AAD, so we can avoid
|
||||
// reading the actual data for those from the fuzzer input (which would need large amounts of
|
||||
// data).
|
||||
XoRoShiRo128PlusPlus rng(provider.ConsumeIntegral<uint64_t>());
|
||||
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
|
||||
|
||||
// Compare session IDs and garbage terminators.
|
||||
assert(initiator.GetSessionID() == responder.GetSessionID());
|
||||
@@ -79,10 +79,8 @@ FUZZ_TARGET(bip324_cipher_roundtrip, .init=Initialize)
|
||||
unsigned length_bits = 2 * ((mode >> 5) & 7);
|
||||
unsigned length = provider.ConsumeIntegralInRange<unsigned>(0, (1 << length_bits) - 1);
|
||||
// Generate aad and content.
|
||||
std::vector<std::byte> aad(aad_length);
|
||||
for (auto& val : aad) val = std::byte{(uint8_t)rng()};
|
||||
std::vector<std::byte> contents(length);
|
||||
for (auto& val : contents) val = std::byte{(uint8_t)rng()};
|
||||
auto aad = rng.randbytes<std::byte>(aad_length);
|
||||
auto contents = rng.randbytes<std::byte>(length);
|
||||
|
||||
// Pick sides.
|
||||
auto& sender{from_init ? initiator : responder};
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <random.h>
|
||||
#include <span.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
#include <util/bitset.h>
|
||||
|
||||
#include <bitset>
|
||||
@@ -29,7 +29,7 @@ void TestType(FuzzBufferType buffer)
|
||||
* bitsets and their simulations do not matter for the purpose of detecting edge cases, thus
|
||||
* these are taken from a deterministically-seeded RNG instead. To provide some level of
|
||||
* variation however, pick the seed based on the buffer size and size of the chosen bitset. */
|
||||
XoRoShiRo128PlusPlus rng(buffer.size() + 0x10000 * S::Size());
|
||||
InsecureRandomContext rng(buffer.size() + 0x10000 * S::Size());
|
||||
|
||||
using Sim = std::bitset<S::Size()>;
|
||||
// Up to 4 real BitSets (initially 2).
|
||||
@@ -124,7 +124,7 @@ void TestType(FuzzBufferType buffer)
|
||||
sim[dest].reset();
|
||||
real[dest] = S{};
|
||||
for (unsigned i = 0; i < S::Size(); ++i) {
|
||||
if (rng() & 1) {
|
||||
if (rng.randbool()) {
|
||||
sim[dest][i] = true;
|
||||
real[dest].Set(i);
|
||||
}
|
||||
@@ -132,9 +132,9 @@ void TestType(FuzzBufferType buffer)
|
||||
break;
|
||||
} else if (dest < sim.size() && command-- == 0) {
|
||||
/* Assign initializer list. */
|
||||
unsigned r1 = rng() % S::Size();
|
||||
unsigned r2 = rng() % S::Size();
|
||||
unsigned r3 = rng() % S::Size();
|
||||
unsigned r1 = rng.randrange(S::Size());
|
||||
unsigned r2 = rng.randrange(S::Size());
|
||||
unsigned r3 = rng.randrange(S::Size());
|
||||
compare_fn(dest);
|
||||
sim[dest].reset();
|
||||
real[dest] = {r1, r2, r3};
|
||||
@@ -166,8 +166,8 @@ void TestType(FuzzBufferType buffer)
|
||||
break;
|
||||
} else if (sim.size() < 4 && command-- == 0) {
|
||||
/* Construct with initializer list. */
|
||||
unsigned r1 = rng() % S::Size();
|
||||
unsigned r2 = rng() % S::Size();
|
||||
unsigned r1 = rng.randrange(S::Size());
|
||||
unsigned r2 = rng.randrange(S::Size());
|
||||
sim.emplace_back();
|
||||
sim.back().set(r1);
|
||||
sim.back().set(r2);
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <crypto/chacha20.h>
|
||||
#include <random.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
@@ -53,7 +53,7 @@ namespace
|
||||
once for a large block at once, and then the same data in chunks, comparing
|
||||
the outcome.
|
||||
|
||||
If UseCrypt, seeded Xoroshiro128++ output is used as input to Crypt().
|
||||
If UseCrypt, seeded InsecureRandomContext output is used as input to Crypt().
|
||||
If not, Keystream() is used directly, or sequences of 0x00 are encrypted.
|
||||
*/
|
||||
template<bool UseCrypt>
|
||||
@@ -78,25 +78,11 @@ void ChaCha20SplitFuzz(FuzzedDataProvider& provider)
|
||||
data1.resize(total_bytes);
|
||||
data2.resize(total_bytes);
|
||||
|
||||
// If using Crypt(), initialize data1 and data2 with the same Xoroshiro128++ based
|
||||
// If using Crypt(), initialize data1 and data2 with the same InsecureRandomContext based
|
||||
// stream.
|
||||
if constexpr (UseCrypt) {
|
||||
uint64_t seed = provider.ConsumeIntegral<uint64_t>();
|
||||
XoRoShiRo128PlusPlus rng(seed);
|
||||
uint64_t bytes = 0;
|
||||
while (bytes < (total_bytes & ~uint64_t{7})) {
|
||||
uint64_t val = rng();
|
||||
WriteLE64(UCharCast(data1.data() + bytes), val);
|
||||
WriteLE64(UCharCast(data2.data() + bytes), val);
|
||||
bytes += 8;
|
||||
}
|
||||
if (bytes < total_bytes) {
|
||||
std::byte valbytes[8];
|
||||
uint64_t val = rng();
|
||||
WriteLE64(UCharCast(valbytes), val);
|
||||
std::copy(valbytes, valbytes + (total_bytes - bytes), data1.data() + bytes);
|
||||
std::copy(valbytes, valbytes + (total_bytes - bytes), data2.data() + bytes);
|
||||
}
|
||||
InsecureRandomContext(provider.ConsumeIntegral<uint64_t>()).fillrand(data1);
|
||||
std::copy(data1.begin(), data1.end(), data2.begin());
|
||||
}
|
||||
|
||||
// Whether UseCrypt is used or not, the two byte arrays must match.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <test/util/random.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/check.h>
|
||||
#include <util/fs.h>
|
||||
@@ -101,6 +102,12 @@ void ResetCoverageCounters() {}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
// By default, make the RNG deterministic with a fixed seed. This will affect all
|
||||
// randomness during the fuzz test, except:
|
||||
// - GetStrongRandBytes(), which is used for the creation of private key material.
|
||||
// - Creating a BasicTestingSetup or derived class will switch to a random seed.
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
|
||||
// Terminate immediately if a fuzzing harness ever tries to create a socket.
|
||||
// Individual tests can override this by pointing CreateSock to a mocked alternative.
|
||||
CreateSock = [](int, int, int) -> std::unique_ptr<Sock> { std::terminate(); };
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
#include <util/chaintype.h>
|
||||
|
||||
#include <cassert>
|
||||
@@ -104,7 +103,7 @@ FUZZ_TARGET(p2p_transport_serialization, .init = initialize_p2p_transport_serial
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename R>
|
||||
template<RandomNumberGenerator R>
|
||||
void SimulationTest(Transport& initiator, Transport& responder, R& rng, FuzzedDataProvider& provider)
|
||||
{
|
||||
// Simulation test with two Transport objects, which send messages to each other, with
|
||||
@@ -165,8 +164,7 @@ void SimulationTest(Transport& initiator, Transport& responder, R& rng, FuzzedDa
|
||||
// Determine size of message to send (limited to 75 kB for performance reasons).
|
||||
size_t size = provider.ConsumeIntegralInRange<uint32_t>(0, 75000);
|
||||
// Get payload of message from RNG.
|
||||
msg.data.resize(size);
|
||||
for (auto& v : msg.data) v = uint8_t(rng());
|
||||
msg.data = rng.randbytes(size);
|
||||
// Return.
|
||||
return msg;
|
||||
};
|
||||
@@ -337,7 +335,7 @@ std::unique_ptr<Transport> MakeV1Transport(NodeId nodeid) noexcept
|
||||
return std::make_unique<V1Transport>(nodeid);
|
||||
}
|
||||
|
||||
template<typename RNG>
|
||||
template<RandomNumberGenerator RNG>
|
||||
std::unique_ptr<Transport> MakeV2Transport(NodeId nodeid, bool initiator, RNG& rng, FuzzedDataProvider& provider)
|
||||
{
|
||||
// Retrieve key
|
||||
@@ -353,8 +351,7 @@ std::unique_ptr<Transport> MakeV2Transport(NodeId nodeid, bool initiator, RNG& r
|
||||
} else {
|
||||
// If it's longer, generate it from the RNG. This avoids having large amounts of
|
||||
// (hopefully) irrelevant data needing to be stored in the fuzzer data.
|
||||
garb.resize(garb_len);
|
||||
for (auto& v : garb) v = uint8_t(rng());
|
||||
garb = rng.randbytes(garb_len);
|
||||
}
|
||||
// Retrieve entropy
|
||||
auto ent = provider.ConsumeBytes<std::byte>(32);
|
||||
@@ -378,7 +375,7 @@ FUZZ_TARGET(p2p_transport_bidirectional, .init = initialize_p2p_transport_serial
|
||||
{
|
||||
// Test with two V1 transports talking to each other.
|
||||
FuzzedDataProvider provider{buffer.data(), buffer.size()};
|
||||
XoRoShiRo128PlusPlus rng(provider.ConsumeIntegral<uint64_t>());
|
||||
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
|
||||
auto t1 = MakeV1Transport(NodeId{0});
|
||||
auto t2 = MakeV1Transport(NodeId{1});
|
||||
if (!t1 || !t2) return;
|
||||
@@ -389,7 +386,7 @@ FUZZ_TARGET(p2p_transport_bidirectional_v2, .init = initialize_p2p_transport_ser
|
||||
{
|
||||
// Test with two V2 transports talking to each other.
|
||||
FuzzedDataProvider provider{buffer.data(), buffer.size()};
|
||||
XoRoShiRo128PlusPlus rng(provider.ConsumeIntegral<uint64_t>());
|
||||
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
|
||||
auto t1 = MakeV2Transport(NodeId{0}, true, rng, provider);
|
||||
auto t2 = MakeV2Transport(NodeId{1}, false, rng, provider);
|
||||
if (!t1 || !t2) return;
|
||||
@@ -400,7 +397,7 @@ FUZZ_TARGET(p2p_transport_bidirectional_v1v2, .init = initialize_p2p_transport_s
|
||||
{
|
||||
// Test with a V1 initiator talking to a V2 responder.
|
||||
FuzzedDataProvider provider{buffer.data(), buffer.size()};
|
||||
XoRoShiRo128PlusPlus rng(provider.ConsumeIntegral<uint64_t>());
|
||||
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
|
||||
auto t1 = MakeV1Transport(NodeId{0});
|
||||
auto t2 = MakeV2Transport(NodeId{1}, false, rng, provider);
|
||||
if (!t1 || !t2) return;
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <random.h>
|
||||
#include <span.h>
|
||||
#include <support/allocators/pool.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/poolresourcetester.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
@@ -71,41 +71,14 @@ public:
|
||||
|
||||
void RandomContentFill(Entry& entry)
|
||||
{
|
||||
XoRoShiRo128PlusPlus rng(entry.seed);
|
||||
auto ptr = entry.span.data();
|
||||
auto size = entry.span.size();
|
||||
|
||||
while (size >= 8) {
|
||||
auto r = rng();
|
||||
std::memcpy(ptr, &r, 8);
|
||||
size -= 8;
|
||||
ptr += 8;
|
||||
}
|
||||
if (size > 0) {
|
||||
auto r = rng();
|
||||
std::memcpy(ptr, &r, size);
|
||||
}
|
||||
InsecureRandomContext(entry.seed).fillrand(entry.span);
|
||||
}
|
||||
|
||||
void RandomContentCheck(const Entry& entry)
|
||||
{
|
||||
XoRoShiRo128PlusPlus rng(entry.seed);
|
||||
auto ptr = entry.span.data();
|
||||
auto size = entry.span.size();
|
||||
|
||||
std::byte buf[8];
|
||||
while (size >= 8) {
|
||||
auto r = rng();
|
||||
std::memcpy(buf, &r, 8);
|
||||
assert(std::memcmp(buf, ptr, 8) == 0);
|
||||
size -= 8;
|
||||
ptr += 8;
|
||||
}
|
||||
if (size > 0) {
|
||||
auto r = rng();
|
||||
std::memcpy(buf, &r, size);
|
||||
assert(std::memcmp(buf, ptr, size) == 0);
|
||||
}
|
||||
std::vector<std::byte> expect(entry.span.size());
|
||||
InsecureRandomContext(entry.seed).fillrand(expect);
|
||||
assert(entry.span == expect);
|
||||
}
|
||||
|
||||
void Deallocate(const Entry& entry)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <random.h>
|
||||
#include <span.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/xoroshiro128plusplus.h>
|
||||
#include <util/vecdeque.h>
|
||||
|
||||
#include <deque>
|
||||
@@ -28,7 +28,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
{
|
||||
FuzzedDataProvider provider(buffer.data(), buffer.size());
|
||||
// Local RNG, only used for the seeds to initialize T objects with.
|
||||
XoRoShiRo128PlusPlus rng(provider.ConsumeIntegral<uint64_t>() ^ rng_tweak);
|
||||
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>() ^ rng_tweak);
|
||||
|
||||
// Real circular buffers.
|
||||
std::vector<VecDeque<T>> real;
|
||||
@@ -175,7 +175,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* push_back() (copying) */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
real[idx].push_back(*tmp);
|
||||
@@ -191,7 +191,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* push_back() (moving) */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
sim[idx].push_back(*tmp);
|
||||
@@ -207,7 +207,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* emplace_back() */
|
||||
uint64_t seed{rng()};
|
||||
uint64_t seed{rng.rand64()};
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
sim[idx].emplace_back(seed);
|
||||
@@ -223,7 +223,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* push_front() (copying) */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
real[idx].push_front(*tmp);
|
||||
@@ -239,7 +239,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* push_front() (moving) */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
sim[idx].push_front(*tmp);
|
||||
@@ -255,7 +255,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_full && command-- == 0) {
|
||||
/* emplace_front() */
|
||||
uint64_t seed{rng()};
|
||||
uint64_t seed{rng.rand64()};
|
||||
size_t old_size = real[idx].size();
|
||||
size_t old_cap = real[idx].capacity();
|
||||
sim[idx].emplace_front(seed);
|
||||
@@ -271,7 +271,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_empty && command-- == 0) {
|
||||
/* front() [modifying] */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
assert(sim[idx].front() == real[idx].front());
|
||||
sim[idx].front() = *tmp;
|
||||
@@ -281,7 +281,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_empty && command-- == 0) {
|
||||
/* back() [modifying] */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t old_size = real[idx].size();
|
||||
assert(sim[idx].back() == real[idx].back());
|
||||
sim[idx].back() = *tmp;
|
||||
@@ -291,7 +291,7 @@ void TestType(Span<const uint8_t> buffer, uint64_t rng_tweak)
|
||||
}
|
||||
if (existing_buffer_non_empty && command-- == 0) {
|
||||
/* operator[] [modifying] */
|
||||
tmp = T(rng());
|
||||
tmp = T(rng.rand64());
|
||||
size_t pos = provider.ConsumeIntegralInRange<size_t>(0, sim[idx].size() - 1);
|
||||
size_t old_size = real[idx].size();
|
||||
assert(sim[idx][pos] == real[idx][pos]);
|
||||
|
||||
Reference in New Issue
Block a user