Commit 511ad649 by Derek Mauro Committed by Copybara-Service

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
parent ac39cc1e
...@@ -274,7 +274,7 @@ ...@@ -274,7 +274,7 @@
// //
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. // Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. // See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize) #if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else #else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
......
...@@ -1621,6 +1621,11 @@ TEST(DynamicVec, DynamicVecCompiles) { ...@@ -1621,6 +1621,11 @@ TEST(DynamicVec, DynamicVecCompiles) {
(void)v; (void)v;
} }
TEST(DynamicVec, CreateNonEmptyDynamicVec) {
DynamicVec v(1);
EXPECT_EQ(v.size(), 1u);
}
TEST(AllocatorSupportTest, Constructors) { TEST(AllocatorSupportTest, Constructors) {
using MyAlloc = CountingAllocator<int>; using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
......
...@@ -391,13 +391,22 @@ class Storage { ...@@ -391,13 +391,22 @@ class Storage {
} }
Pointer<A> GetInlinedData() { Pointer<A> GetInlinedData() {
return reinterpret_cast<Pointer<A>>( return reinterpret_cast<Pointer<A>>(data_.inlined.inlined_data);
std::addressof(data_.inlined.inlined_data[0]));
} }
ConstPointer<A> GetInlinedData() const { ConstPointer<A> GetInlinedData() const {
return reinterpret_cast<ConstPointer<A>>( return reinterpret_cast<ConstPointer<A>>(data_.inlined.inlined_data);
std::addressof(data_.inlined.inlined_data[0])); }
// 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 { SizeType<A> GetAllocatedCapacity() const {
...@@ -628,7 +637,7 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size) ...@@ -628,7 +637,7 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size)
SetAllocation(allocation); SetAllocation(allocation);
SetIsAllocated(); SetIsAllocated();
} else { } else {
construct_data = GetInlinedData(); construct_data = GetInlinedDataUninitialized();
} }
ConstructElements<A>(GetAllocator(), construct_data, values, new_size); ConstructElements<A>(GetAllocator(), construct_data, values, new_size);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment