Skip to content

Commit a7875bb

Browse files
Remove the time (or time-based) entropy being added to Map's seed.
This is similar in effect to if GOOGLE_PROTOBUF_NO_RDTSC define was enabled always. Hashing the address of the table plus the per-process entropy added by absl::Hash is sufficient amount of entropy for this usecase. PiperOrigin-RevId: 696982713
1 parent 254f1e8 commit a7875bb

File tree

2 files changed

+3
-90
lines changed

2 files changed

+3
-90
lines changed

src/google/protobuf/map.h

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@
3131
#include "absl/memory/memory.h"
3232
#include "google/protobuf/message_lite.h"
3333

34-
#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) && \
35-
(!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
36-
#include <time.h>
37-
#endif
38-
3934
#include "absl/base/attributes.h"
4035
#include "absl/container/btree_map.h"
4136
#include "absl/hash/hash.h"
@@ -563,7 +558,6 @@ class PROTOBUF_EXPORT UntypedMapBase {
563558
explicit constexpr UntypedMapBase(Arena* arena)
564559
: num_elements_(0),
565560
num_buckets_(internal::kGlobalEmptyTableSize),
566-
seed_(0),
567561
index_of_first_non_null_(internal::kGlobalEmptyTableSize),
568562
table_(const_cast<TableEntryPtr*>(internal::kGlobalEmptyTable)),
569563
alloc_(arena) {}
@@ -581,7 +575,6 @@ class PROTOBUF_EXPORT UntypedMapBase {
581575
void InternalSwap(UntypedMapBase* other) {
582576
std::swap(num_elements_, other->num_elements_);
583577
std::swap(num_buckets_, other->num_buckets_);
584-
std::swap(seed_, other->seed_);
585578
std::swap(index_of_first_non_null_, other->index_of_first_non_null_);
586579
std::swap(table_, other->table_);
587580
std::swap(alloc_, other->alloc_);
@@ -621,7 +614,7 @@ class PROTOBUF_EXPORT UntypedMapBase {
621614
return false;
622615
#else
623616
// Doing modulo with a prime mixes the bits more.
624-
return (reinterpret_cast<uintptr_t>(node) ^ seed_) % 13 > 6;
617+
return absl::HashOf(node, table_) % 13 > 6;
625618
#endif
626619
}
627620

@@ -708,12 +701,12 @@ class PROTOBUF_EXPORT UntypedMapBase {
708701
}
709702

710703
map_index_t VariantBucketNumber(absl::string_view key) const {
711-
return static_cast<map_index_t>(absl::HashOf(seed_, key) &
704+
return static_cast<map_index_t>(absl::HashOf(key, table_) &
712705
(num_buckets_ - 1));
713706
}
714707

715708
map_index_t VariantBucketNumber(uint64_t key) const {
716-
return static_cast<map_index_t>(absl::HashOf(key ^ seed_) &
709+
return static_cast<map_index_t>(absl::HashOf(key, table_) &
717710
(num_buckets_ - 1));
718711
}
719712

@@ -725,34 +718,6 @@ class PROTOBUF_EXPORT UntypedMapBase {
725718
return result;
726719
}
727720

728-
// Return a randomish value.
729-
map_index_t Seed() const {
730-
uint64_t s = 0;
731-
#if !defined(GOOGLE_PROTOBUF_NO_RDTSC)
732-
#if defined(__APPLE__) && \
733-
(!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
734-
// Use a commpage-based fast time function on Apple environments (MacOS,
735-
// iOS, tvOS, watchOS, etc), if we think the system headers expose it.
736-
s = clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
737-
#elif defined(__x86_64__) && defined(__GNUC__)
738-
uint32_t hi, lo;
739-
asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
740-
s = ((static_cast<uint64_t>(hi) << 32) | lo);
741-
#elif defined(__aarch64__) && defined(__GNUC__)
742-
// There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the
743-
// system timer. It runs at a different frequency than the CPU's, but is
744-
// the best source of time-based entropy we get.
745-
uint64_t virtual_timer_value;
746-
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
747-
s = virtual_timer_value;
748-
#endif
749-
#endif // !defined(GOOGLE_PROTOBUF_NO_RDTSC)
750-
// Add entropy from the address of the map and the address of the table
751-
// array.
752-
return static_cast<map_index_t>(
753-
absl::HashOf(s, table_, static_cast<const void*>(this)));
754-
}
755-
756721
enum {
757722
kKeyIsString = 1 << 0,
758723
kValueIsString = 1 << 1,
@@ -812,7 +777,6 @@ class PROTOBUF_EXPORT UntypedMapBase {
812777

813778
map_index_t num_elements_;
814779
map_index_t num_buckets_;
815-
map_index_t seed_;
816780
map_index_t index_of_first_non_null_;
817781
TableEntryPtr* table_; // an array with num_buckets_ entries
818782
Allocator alloc_;
@@ -1096,7 +1060,6 @@ class KeyMapBase : public UntypedMapBase {
10961060
// Just overwrite with a new one. No need to transfer or free anything.
10971061
num_buckets_ = index_of_first_non_null_ = kMinTableSize;
10981062
table_ = CreateEmptyTable(num_buckets_);
1099-
seed_ = Seed();
11001063
return;
11011064
}
11021065

src/google/protobuf/map_test.inc

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,6 @@ struct MapTestPeer {
201201
map.Resize(num_buckets);
202202
}
203203

204-
template <typename T>
205-
static bool HasTreeBuckets(T& map) {
206-
for (size_t i = 0; i < map.num_buckets_; ++i) {
207-
if (TableEntryIsTree(map.table_[i])) return true;
208-
}
209-
return false;
210-
}
211-
212204
static int CalculateHiCutoff(int num_buckets) {
213205
return Map<int, int>::CalculateHiCutoff(num_buckets);
214206
}
@@ -513,48 +505,6 @@ static int k0 = 812398771;
513505
static int k1 = 1312938717;
514506
static int k2 = 1321555333;
515507

516-
// Finds inputs that will fall in the first few buckets for this particular map
517-
// (with the random seed it has) and this particular size.
518-
static std::vector<int> FindBadInputs(Map<int, int>& map, int num_inputs) {
519-
// Make sure the seed and the size is set so that BucketNumber works.
520-
while (map.size() < num_inputs) map[map.size()];
521-
map.clear();
522-
523-
std::vector<int> out;
524-
525-
for (int i = 0; out.size() < num_inputs; ++i) {
526-
if (MapTestPeer::BucketNumber(map, i) < 3) {
527-
out.push_back(i);
528-
}
529-
}
530-
531-
// Reset the table to get it to grow from scratch again.
532-
// The capacity will be lost, but we will get it again on insertion.
533-
// It will also keep the seed.
534-
map.clear();
535-
MapTestPeer::Resize(map, 8);
536-
537-
return out;
538-
}
539-
540-
TEST_F(MapImplTest, TreePathWorksAsExpected) {
541-
const std::vector<int> s = FindBadInputs(map_, 1000);
542-
543-
for (int i : s) {
544-
map_[i] = 0;
545-
}
546-
// Make sure we are testing what we think we are testing.
547-
ASSERT_TRUE(MapTestPeer::HasTreeBuckets(map_));
548-
for (int i : s) {
549-
ASSERT_NE(map_.find(i), map_.end()) << i;
550-
}
551-
for (int i : s) {
552-
ASSERT_EQ(1, map_.erase(i)) << i;
553-
}
554-
EXPECT_FALSE(MapTestPeer::HasTreeBuckets(map_));
555-
EXPECT_TRUE(map_.empty());
556-
}
557-
558508

559509
TEST_F(MapImplTest, CopyIteratorStressTest) {
560510
std::vector<Map<int32_t, int32_t>::iterator> v;

0 commit comments

Comments
 (0)