aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ADT/SmallVectorTest.cpp
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2020-11-19 16:58:16 -0800
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2021-01-13 20:00:44 -0800
commit3043e5a5c33c4c871f4a1dfd621a8839f9a1f0b3 (patch)
tree8dbfd83bd484d863d9266845d7333b3194884b77 /llvm/unittests/ADT/SmallVectorTest.cpp
parent49142991a685bd427d7e877c29c77371dfb7634c (diff)
downloadllvm-3043e5a5c33c4c871f4a1dfd621a8839f9a1f0b3.zip
llvm-3043e5a5c33c4c871f4a1dfd621a8839f9a1f0b3.tar.gz
llvm-3043e5a5c33c4c871f4a1dfd621a8839f9a1f0b3.tar.bz2
ADT: Fix reference invalidation in N-element SmallVector::append and insert
For small enough, trivially copyable `T`, take the parameter by-value in `SmallVector::append` and `SmallVector::insert`. Otherwise, when growing, update the arugment appropriately. Differential Revision: https://reviews.llvm.org/D93780
Diffstat (limited to 'llvm/unittests/ADT/SmallVectorTest.cpp')
-rw-r--r--llvm/unittests/ADT/SmallVectorTest.cpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp
index c880a6b..c236a68 100644
--- a/llvm/unittests/ADT/SmallVectorTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -1146,9 +1146,17 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) {
TYPED_TEST(SmallVectorReferenceInvalidationTest, Append) {
auto &V = this->V;
(void)V;
-#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
- EXPECT_DEATH(V.append(1, V.back()), this->AssertionMessage);
-#endif
+ V.append(1, V.back());
+ int N = this->NumBuiltinElts(V);
+ EXPECT_EQ(N, V[N - 1]);
+
+ // Append enough more elements that V will grow again. This tests growing
+ // when already in large mode.
+ //
+ // If reference invalidation breaks in the future, sanitizers should be able
+ // to catch a use-after-free here.
+ V.append(V.capacity() - V.size() + 1, V.front());
+ EXPECT_EQ(1, V.back());
}
TYPED_TEST(SmallVectorReferenceInvalidationTest, AppendRange) {
@@ -1244,9 +1252,20 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertMoved) {
TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertN) {
auto &V = this->V;
(void)V;
-#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
- EXPECT_DEATH(V.insert(V.begin(), 2, V.back()), this->AssertionMessage);
-#endif
+
+ // Cover NumToInsert <= this->end() - I.
+ V.insert(V.begin() + 1, 1, V.back());
+ int N = this->NumBuiltinElts(V);
+ EXPECT_EQ(N, V[1]);
+
+ // Cover NumToInsert > this->end() - I, inserting enough elements that V will
+ // also grow again; V.capacity() will be more elements than necessary but
+ // it's a simple way to cover both conditions.
+ //
+ // If reference invalidation breaks in the future, sanitizers should be able
+ // to catch a use-after-free here.
+ V.insert(V.begin(), V.capacity(), V.front());
+ EXPECT_EQ(1, V.front());
}
TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertRange) {