summaryrefslogtreecommitdiff
path: root/absl/random/internal/nonsecure_base.h
diff options
context:
space:
mode:
authorGravatar Laramie Leavitt <lar@google.com>2022-06-02 10:08:08 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-06-02 10:08:59 -0700
commitbed94589f27d7fdfa34ede5988203369d170cec3 (patch)
treef2ea3f182f59b1c360b82ce1969cf7a61c00033c /absl/random/internal/nonsecure_base.h
parentc34c552a1a547a47474f32f1b89de030aa4ff949 (diff)
Rework NonsecureURBGBase seed sequence.
Decompose RandenPoolSeedSeq from NonsecureURBGBase. Adjust how the RandenPoolSeedSeq detects contiguous buffers passed to the generate function. Previously it made incorrect assumptions regarding the contiguous concept, which have been replaced with some type-based tests for a small number of known contiguous random access iterator types, including raw pointers. PiperOrigin-RevId: 452564114 Change-Id: Idab1df9dd078d8e5c565c7fa7ccb9c0d3d392ad2
Diffstat (limited to 'absl/random/internal/nonsecure_base.h')
-rw-r--r--absl/random/internal/nonsecure_base.h107
1 files changed, 59 insertions, 48 deletions
diff --git a/absl/random/internal/nonsecure_base.h b/absl/random/internal/nonsecure_base.h
index 730fa2ea..c7d7fa4b 100644
--- a/absl/random/internal/nonsecure_base.h
+++ b/absl/random/internal/nonsecure_base.h
@@ -17,28 +17,82 @@
#include <algorithm>
#include <cstdint>
-#include <iostream>
#include <iterator>
-#include <random>
-#include <string>
#include <type_traits>
+#include <utility>
#include <vector>
#include "absl/base/macros.h"
+#include "absl/container/inlined_vector.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/pool_urbg.h"
#include "absl/random/internal/salted_seed_seq.h"
#include "absl/random/internal/seed_material.h"
-#include "absl/types/optional.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
+// RandenPoolSeedSeq is a custom seed sequence type where generate() fills the
+// provided buffer via the RandenPool entropy source.
+class RandenPoolSeedSeq {
+ private:
+ struct ContiguousTag {};
+ struct BufferTag {};
+
+ // Generate random unsigned values directly into the buffer.
+ template <typename Contiguous>
+ void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {
+ const size_t n = std::distance(begin, end);
+ auto* a = &(*begin);
+ RandenPool<uint8_t>::Fill(
+ absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n));
+ }
+
+ // Construct a buffer of size n and fill it with values, then copy
+ // those values into the seed iterators.
+ template <typename RandomAccessIterator>
+ void generate_impl(BufferTag, RandomAccessIterator begin,
+ RandomAccessIterator end) {
+ const size_t n = std::distance(begin, end);
+ absl::InlinedVector<uint32_t, 8> data(n, 0);
+ RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
+ std::copy(std::begin(data), std::end(data), begin);
+ }
+
+ public:
+ using result_type = uint32_t;
+
+ size_t size() { return 0; }
+
+ template <typename OutIterator>
+ void param(OutIterator) const {}
+
+ template <typename RandomAccessIterator>
+ void generate(RandomAccessIterator begin, RandomAccessIterator end) {
+ // RandomAccessIterator must be assignable from uint32_t
+ if (begin != end) {
+ using U = typename std::iterator_traits<RandomAccessIterator>::value_type;
+ // ContiguousTag indicates the common case of a known contiguous buffer,
+ // which allows directly filling the buffer. In C++20,
+ // std::contiguous_iterator_tag provides a mechanism for testing this
+ // capability, however until Abseil's support requirements allow us to
+ // assume C++20, limit checks to a few common cases.
+ using TagType = absl::conditional_t<
+ (std::is_pointer<RandomAccessIterator>::value ||
+ std::is_same<RandomAccessIterator,
+ typename std::vector<U>::iterator>::value),
+ ContiguousTag, BufferTag>;
+
+ generate_impl(TagType{}, begin, end);
+ }
+ }
+};
+
// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
// by a thread-unique URBG-instance.
-template <typename URBG>
+template <typename URBG, typename Seeder = RandenPoolSeedSeq>
class NonsecureURBGBase {
public:
using result_type = typename URBG::result_type;
@@ -85,49 +139,6 @@ class NonsecureURBGBase {
}
private:
- // Seeder is a custom seed sequence type where generate() fills the provided
- // buffer via the RandenPool entropy source.
- struct Seeder {
- using result_type = uint32_t;
-
- size_t size() { return 0; }
-
- template <typename OutIterator>
- void param(OutIterator) const {}
-
- template <typename RandomAccessIterator>
- void generate(RandomAccessIterator begin, RandomAccessIterator end) {
- if (begin != end) {
- // begin, end must be random access iterators assignable from uint32_t.
- generate_impl(
- std::integral_constant<bool, sizeof(*begin) == sizeof(uint32_t)>{},
- begin, end);
- }
- }
-
- // Commonly, generate is invoked with a pointer to a buffer which
- // can be cast to a uint32_t.
- template <typename RandomAccessIterator>
- void generate_impl(std::integral_constant<bool, true>,
- RandomAccessIterator begin, RandomAccessIterator end) {
- auto buffer = absl::MakeSpan(begin, end);
- auto target = absl::MakeSpan(reinterpret_cast<uint32_t*>(buffer.data()),
- buffer.size());
- RandenPool<uint32_t>::Fill(target);
- }
-
- // The non-uint32_t case should be uncommon, and involves an extra copy,
- // filling the uint32_t buffer and then mixing into the output.
- template <typename RandomAccessIterator>
- void generate_impl(std::integral_constant<bool, false>,
- RandomAccessIterator begin, RandomAccessIterator end) {
- const size_t n = std::distance(begin, end);
- absl::InlinedVector<uint32_t, 8> data(n, 0);
- RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
- std::copy(std::begin(data), std::end(data), begin);
- }
- };
-
static URBG ConstructURBG() {
Seeder seeder;
return URBG(seeder);