From 8fb4507d10a24a1204e98f77ad19c27c291e13e9 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 19 May 2026 15:45:07 -0700 Subject: [PATCH] Fix strict aliasing violation in node_hash_map node_hash_map uses the function TypeErasedDerefAndApplyToSlotFn to hash a slot's key. This function accesses a slot pointer as if it were of type Key* when in fact it is of type value_type* (aka std::pair *). This is technically a strict aliasing violation because the types of the pointer objects are different. Fix it by defining a new type erased function TypeErasedDerefAndApplyToSlotFirstFn that uses the correct type for the pointer. PiperOrigin-RevId: 918067685 Change-Id: I5d65e0e077f84a0f869be0e24fee094b4b09fbfb --- absl/container/internal/container_memory.h | 12 +++++++++++- absl/container/node_hash_map.h | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index fc7633f1..16a2e25a 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -550,10 +550,20 @@ template size_t TypeErasedDerefAndApplyToSlotFn(const void* fn, void* slot_ptr, size_t seed) { const auto* f = static_cast(fn); - const T* slot = *static_cast(slot_ptr); + const T* slot = *static_cast(slot_ptr); return HashElement{*f, seed}(*slot); } +// Type erased function to apply `Fn` to data inside of the `slot_ptr->first`. +// The data is expected to have type `T`. +template +size_t TypeErasedDerefAndApplyToSlotFirstFn(const void* fn, void* slot_ptr, + size_t seed) { + const auto* f = static_cast(fn); + const T* slot = *static_cast(slot_ptr); + return HashElement{*f, seed}(slot->first); +} + } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index e9130058..a58680ab 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -681,7 +681,8 @@ class NodeHashMapPolicy template static constexpr HashSlotFn get_hash_slot_fn() { return memory_internal::IsLayoutCompatible::value - ? &TypeErasedDerefAndApplyToSlotFn + ? &TypeErasedDerefAndApplyToSlotFirstFn : nullptr; } };