Author: Duncan P. N. Exon Smith Date: 2021-01-13T20:48:08-08:00 New Revision: 260a856c2abcef49c7cb3bdcd999701db3e2af38
URL: https://github.com/llvm/llvm-project/commit/260a856c2abcef49c7cb3bdcd999701db3e2af38 DIFF: https://github.com/llvm/llvm-project/commit/260a856c2abcef49c7cb3bdcd999701db3e2af38.diff LOG: ADT: Fix reference invalidation in SmallVector::resize For small enough, trivially copyable `T`, take the parameter by-value in `SmallVector::resize`. Otherwise, when growing, update the arugment appropriately. Differential Revision: https://reviews.llvm.org/D93781 Added: Modified: llvm/include/llvm/ADT/SmallVector.h llvm/unittests/ADT/SmallVectorTest.cpp Removed: ################################################################################ diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index fea8a763d48f..ac445e556ba1 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -565,7 +565,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> { /// Like resize, but \ref T is POD, the new values won't be initialized. void resize_for_overwrite(size_type N) { resizeImpl<true>(N); } - void resize(size_type N, const T &NV) { + void resize(size_type N, ValueParamT NV) { if (N == this->size()) return; @@ -575,11 +575,8 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> { return; } - this->assertSafeToReferenceAfterResize(&NV, N); - if (this->capacity() < N) - this->grow(N); - std::uninitialized_fill(this->end(), this->begin() + N, NV); - this->set_size(N); + // N > this->size(). Defer to append. + this->append(N - this->size(), NV); } void reserve(size_type N) { diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index c236a68636d0..1f6c7db99fa8 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -1135,12 +1135,14 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) { auto &V = this->V; (void)V; int N = this->NumBuiltinElts(V); -#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST - EXPECT_DEATH(V.resize(N + 1, V.back()), this->AssertionMessage); -#endif + V.resize(N + 1, V.back()); + EXPECT_EQ(N, V.back()); - // No assertion when shrinking, since the parameter isn't accessed. - V.resize(N - 1, V.back()); + // Resize to add enough elements that V will grow again. If reference + // invalidation breaks in the future, sanitizers should be able to catch a + // use-after-free here. + V.resize(V.capacity() + 1, V.front()); + EXPECT_EQ(1, V.back()); } TYPED_TEST(SmallVectorReferenceInvalidationTest, Append) { _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits