summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2023-07-25 13:04:25 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-07-25 13:05:05 -0700
commit511ad6492eabb7797910ce8689577c45f57bce40 (patch)
tree30dc7f1927894bf57a58e6b17d9445c16c048b61
parentac39cc1ec6fed8d3738b4df9589803c23d6d1e3a (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
-rw-r--r--absl/base/attributes.h2
-rw-r--r--absl/container/inlined_vector_test.cc5
-rw-r--r--absl/container/internal/inlined_vector.h19
3 files changed, 20 insertions, 6 deletions
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index cb3f367f..a7f279a0 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -274,7 +274,7 @@
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// 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")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
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);