1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // REQUIRES: asan
10 // UNSUPPORTED: c++03
11
12 #include <cassert>
13 #include <string>
14 #include <vector>
15 #include <array>
16 #include "test_macros.h"
17 #include "asan_testing.h"
18 #include "min_allocator.h"
19
20 // This tests exists to check if strings work well with vector, as those
21 // may be partialy annotated, we cannot simply call
22 // is_contiguous_container_asan_correct, as it assumes that
23 // object memory inside is not annotated, so we check everything in a more careful way.
24
25 template <typename D>
verify_inside(D const & d)26 void verify_inside(D const& d) {
27 for (size_t i = 0; i < d.size(); ++i) {
28 assert(is_string_asan_correct(d[i]));
29 }
30 }
31
32 template <typename S, size_t N>
get_s(char c)33 S get_s(char c) {
34 S s;
35 for (size_t i = 0; i < N; ++i)
36 s.push_back(c);
37
38 return s;
39 }
40
41 template <class C, class S>
test_string()42 void test_string() {
43 size_t const N = sizeof(S) < 256 ? (4096 / sizeof(S)) : 16;
44
45 {
46 C d1a(1), d1b(N), d1c(N + 1), d1d(5 * N);
47 verify_inside(d1a);
48 verify_inside(d1b);
49 verify_inside(d1c);
50 verify_inside(d1d);
51 }
52 {
53 C d2;
54 for (size_t i = 0; i < 3 * N + 2; ++i) {
55 d2.push_back(get_s<S, 1>(i % 10 + 'a'));
56 verify_inside(d2);
57 d2.push_back(get_s<S, 28>(i % 10 + 'b'));
58 verify_inside(d2);
59
60 d2.erase(d2.cbegin());
61 verify_inside(d2);
62 }
63 }
64 {
65 C d3;
66 for (size_t i = 0; i < 3 * N + 2; ++i) {
67 d3.push_back(get_s<S, 1>(i % 10 + 'a'));
68 verify_inside(d3);
69 d3.push_back(get_s<S, 28>(i % 10 + 'b'));
70 verify_inside(d3);
71
72 d3.pop_back();
73 verify_inside(d3);
74 }
75 }
76 {
77 C d4;
78 for (size_t i = 0; i < 3 * N + 2; ++i) {
79 // When there is no SSO, all elements inside should not be poisoned,
80 // so we can verify vector poisoning.
81 d4.push_back(get_s<S, 33>(i % 10 + 'a'));
82 verify_inside(d4);
83 assert(is_contiguous_container_asan_correct(d4));
84 d4.push_back(get_s<S, 28>(i % 10 + 'b'));
85 verify_inside(d4);
86 assert(is_contiguous_container_asan_correct(d4));
87 }
88 }
89 {
90 C d5;
91 for (size_t i = 0; i < 3 * N + 2; ++i) {
92 // In d4 we never had poisoned memory inside vector.
93 // Here we start with SSO, so part of the inside of the container,
94 // will be poisoned.
95 d5.push_back(S());
96 verify_inside(d5);
97 }
98 for (size_t i = 0; i < d5.size(); ++i) {
99 // We change the size to have long string.
100 // Memory owne by vector should not be poisoned by string.
101 d5[i].resize(100);
102 verify_inside(d5);
103 }
104
105 assert(is_contiguous_container_asan_correct(d5));
106
107 d5.erase(d5.begin() + 2);
108 verify_inside(d5);
109
110 d5.erase(d5.end() - 2);
111 verify_inside(d5);
112
113 assert(is_contiguous_container_asan_correct(d5));
114 }
115 {
116 C d6a;
117 assert(is_contiguous_container_asan_correct(d6a));
118
119 C d6b(N + 2, get_s<S, 100>('a'));
120 d6b.push_back(get_s<S, 101>('b'));
121 while (!d6b.empty()) {
122 d6b.pop_back();
123 assert(is_contiguous_container_asan_correct(d6b));
124 }
125
126 C d6c(N + 2, get_s<S, 102>('c'));
127 while (!d6c.empty()) {
128 d6c.pop_back();
129 assert(is_contiguous_container_asan_correct(d6c));
130 }
131 }
132 {
133 C d7(9 * N + 2);
134
135 d7.insert(d7.begin() + 1, S());
136 verify_inside(d7);
137
138 d7.insert(d7.end() - 3, S());
139 verify_inside(d7);
140
141 d7.insert(d7.begin() + 2 * N, get_s<S, 1>('a'));
142 verify_inside(d7);
143
144 d7.insert(d7.end() - 2 * N, get_s<S, 1>('b'));
145 verify_inside(d7);
146
147 d7.insert(d7.begin() + 2 * N, 3 * N, get_s<S, 1>('c'));
148 verify_inside(d7);
149
150 // It may not be short for big element types, but it will be checked correctly:
151 d7.insert(d7.end() - 2 * N, 3 * N, get_s<S, 2>('d'));
152 verify_inside(d7);
153
154 d7.erase(d7.begin() + 2);
155 verify_inside(d7);
156
157 d7.erase(d7.end() - 2);
158 verify_inside(d7);
159 }
160 }
161
162 template <class S>
test_container()163 void test_container() {
164 test_string<std::vector<S, std::allocator<S>>, S>();
165 test_string<std::vector<S, min_allocator<S>>, S>();
166 test_string<std::vector<S, safe_allocator<S>>, S>();
167 }
168
main(int,char **)169 int main(int, char**) {
170 // Those tests support only types based on std::basic_string.
171 test_container<std::string>();
172 test_container<std::wstring>();
173 #if TEST_STD_VER >= 11
174 test_container<std::u16string>();
175 test_container<std::u32string>();
176 #endif
177 #if TEST_STD_VER >= 20
178 test_container<std::u8string>();
179 #endif
180
181 return 0;
182 }
183