diff options
author | Derek Mauro <dmauro@google.com> | 2023-07-25 13:04:25 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-07-25 13:05:05 -0700 |
commit | 511ad6492eabb7797910ce8689577c45f57bce40 (patch) | |
tree | 30dc7f1927894bf57a58e6b17d9445c16c048b61 /absl/container | |
parent | ac39cc1ec6fed8d3738b4df9589803c23d6d1e3a (diff) |
InlinedVector: Fix control-flow-inregrity warning when using a class
with a vtable
The code is getting the pointer, then constructing it on the next
line. Using reinterpret_cast on this pointer is legal according to
https://clang.llvm.org/docs/ControlFlowIntegrity.html#bad-cast-checking,
but it flags it anyway. The docs say it might be necessary for
`allocate()`-type APIs, and recommends adding them to an ignorelist.
Also note that std::addressof is removed. It is unnecessary since
inlined_data is a char-array.
PiperOrigin-RevId: 550972834
Change-Id: Ib224cec330bb6bcb770296de6c91881f404ef531
Diffstat (limited to 'absl/container')
-rw-r--r-- | absl/container/inlined_vector_test.cc | 5 | ||||
-rw-r--r-- | absl/container/internal/inlined_vector.h | 19 |
2 files changed, 19 insertions, 5 deletions
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc index 6f4625dc..07304518 100644 --- a/absl/container/inlined_vector_test.cc +++ b/absl/container/inlined_vector_test.cc @@ -1621,6 +1621,11 @@ TEST(DynamicVec, DynamicVecCompiles) { (void)v; } +TEST(DynamicVec, CreateNonEmptyDynamicVec) { + DynamicVec v(1); + EXPECT_EQ(v.size(), 1u); +} + TEST(AllocatorSupportTest, Constructors) { using MyAlloc = CountingAllocator<int>; using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h index f886dfa0..639bf145 100644 --- a/absl/container/internal/inlined_vector.h +++ b/absl/container/internal/inlined_vector.h @@ -391,13 +391,22 @@ class Storage { } Pointer<A> GetInlinedData() { - return reinterpret_cast<Pointer<A>>( - std::addressof(data_.inlined.inlined_data[0])); + return reinterpret_cast<Pointer<A>>(data_.inlined.inlined_data); } ConstPointer<A> GetInlinedData() const { - return reinterpret_cast<ConstPointer<A>>( - std::addressof(data_.inlined.inlined_data[0])); + return reinterpret_cast<ConstPointer<A>>(data_.inlined.inlined_data); + } + + // Like GetInlinedData(), but for data that has not been constructed yet. The + // only difference is ABSL_ATTRIBUTE_NO_SANITIZE_CFI, which is necessary + // because the object is uninitialized. + // https://clang.llvm.org/docs/ControlFlowIntegrity.html#bad-cast-checking + // NOTE: When this was written, LLVM documentation did not explicitly + // mention that casting `char*` and using `reinterpret_cast` qualifies + // as a bad cast. + ABSL_ATTRIBUTE_NO_SANITIZE_CFI Pointer<A> GetInlinedDataUninitialized() { + return reinterpret_cast<Pointer<A>>(data_.inlined.inlined_data); } SizeType<A> GetAllocatedCapacity() const { @@ -628,7 +637,7 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size) SetAllocation(allocation); SetIsAllocated(); } else { - construct_data = GetInlinedData(); + construct_data = GetInlinedDataUninitialized(); } ConstructElements<A>(GetAllocator(), construct_data, values, new_size); |