Skip to content

Commit b08a90c

Browse files
vitalybukaAdvenamTacet
authored andcommitted
Simplify the test
1 parent a888e07 commit b08a90c

File tree

1 file changed

+84
-163
lines changed

1 file changed

+84
-163
lines changed

compiler-rt/test/asan/TestCases/copy_container_annotations.cpp

Lines changed: 84 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
// Test __sanitizer_copy_contiguous_container_annotations.
44

55
#include <algorithm>
6-
#include <deque>
6+
#include <iostream>
77
#include <memory>
88
#include <numeric>
9+
#include <vector>
910

1011
#include <assert.h>
1112
#include <sanitizer/asan_interface.h>
@@ -24,212 +25,132 @@ template <class T> static constexpr T RoundUp(T x) {
2425
RoundDown(reinterpret_cast<uintptr_t>(x) + kGranularity - 1));
2526
}
2627

27-
static std::deque<int> GetPoisonedState(char *begin, char *end) {
28-
std::deque<int> result;
28+
static std::vector<int> GetPoisonedState(char *begin, char *end) {
29+
std::vector<int> result;
2930
for (char *ptr = begin; ptr != end; ++ptr) {
3031
result.push_back(__asan_address_is_poisoned(ptr));
3132
}
3233
return result;
3334
}
3435

3536
static void RandomPoison(char *beg, char *end) {
36-
if (beg != RoundDown(beg) && RoundDown(beg) != RoundDown(end) &&
37-
rand() % 2 == 1) {
38-
__asan_poison_memory_region(beg, RoundUp(beg) - beg);
39-
__asan_unpoison_memory_region(beg, rand() % (RoundUp(beg) - beg + 1));
40-
}
37+
assert(beg == RoundDown(beg));
38+
assert(end == RoundDown(end));
4139
for (beg = RoundUp(beg); beg + kGranularity <= end; beg += kGranularity) {
4240
__asan_poison_memory_region(beg, kGranularity);
4341
__asan_unpoison_memory_region(beg, rand() % (kGranularity + 1));
4442
}
45-
if (end > beg && __asan_address_is_poisoned(end)) {
46-
__asan_poison_memory_region(beg, kGranularity);
47-
__asan_unpoison_memory_region(beg, rand() % (end - beg + 1));
48-
}
4943
}
5044

51-
static size_t CountUnpoisoned(std::deque<int> &poison_states, size_t n) {
52-
size_t result = 0;
53-
for (size_t i = 0; i < n && !poison_states.empty(); ++i) {
54-
if (!poison_states.front()) {
55-
result = i + 1;
56-
}
57-
poison_states.pop_front();
45+
static void Test(size_t capacity, size_t off_src, size_t off_dst,
46+
char *src_buffer_beg, char *src_buffer_end,
47+
char *dst_buffer_beg, char *dst_buffer_end) {
48+
size_t dst_buffer_size = dst_buffer_end - dst_buffer_beg;
49+
char *src_beg = src_buffer_beg + off_src;
50+
char *src_end = src_beg + capacity;
51+
52+
char *dst_beg = dst_buffer_beg + off_dst;
53+
char *dst_end = dst_beg + capacity;
54+
55+
std::vector<int> src_poison_states =
56+
GetPoisonedState(src_buffer_beg, src_buffer_end);
57+
std::vector<int> dst_poison_before =
58+
GetPoisonedState(dst_buffer_beg, dst_buffer_end);
59+
__sanitizer_copy_contiguous_container_annotations(src_beg, src_end, dst_beg,
60+
dst_end);
61+
std::vector<int> dst_poison_after =
62+
GetPoisonedState(dst_buffer_beg, dst_buffer_end);
63+
64+
// Create ideal copy of src over dst.
65+
std::vector<int> dst_poison_exp = dst_poison_before;
66+
for (size_t cur = 0; cur < capacity; ++cur)
67+
dst_poison_exp[off_dst + cur] = src_poison_states[off_src + cur];
68+
69+
// Unpoison prefixes of Asan granules.
70+
for (size_t cur = dst_buffer_size - 1; cur > 0; --cur) {
71+
if (cur % kGranularity != 0 && !dst_poison_exp[cur])
72+
dst_poison_exp[cur - 1] = 0;
5873
}
5974

60-
return result;
75+
if (dst_poison_after != dst_poison_exp) {
76+
std::cerr << "[" << off_dst << ", " << off_dst + capacity << ")\n";
77+
for (size_t i = 0; i < dst_poison_after.size(); ++i) {
78+
std::cerr << i << ":\t" << dst_poison_before[i] << "\t"
79+
<< dst_poison_after[i] << "\t" << dst_poison_exp[i] << "\n";
80+
}
81+
std::cerr << "----------\n";
82+
83+
assert(dst_poison_after == dst_poison_exp);
84+
}
6185
}
6286

63-
void TestNonOverlappingContainers(size_t capacity, size_t off_src,
64-
size_t off_dst, bool poison_src,
65-
bool poison_dst) {
66-
size_t src_buffer_size = capacity + off_src + kGranularity * 2;
67-
size_t dst_buffer_size = capacity + off_dst + kGranularity * 2;
87+
static void TestNonOverlappingContainers(size_t capacity, size_t off_src,
88+
size_t off_dst) {
89+
// Test will copy [off_src, off_src + capacity) to [off_dst, off_dst + capacity).
90+
// Allocate buffers to have additional granule before and after tested ranges.
91+
off_src += kGranularity;
92+
off_dst += kGranularity;
93+
size_t src_buffer_size = RoundUp(off_src + capacity) + kGranularity;
94+
size_t dst_buffer_size = RoundUp(off_dst + capacity) + kGranularity;
6895

6996
std::unique_ptr<char[]> src_buffer =
7097
std::make_unique<char[]>(src_buffer_size);
7198
std::unique_ptr<char[]> dst_buffer =
7299
std::make_unique<char[]>(dst_buffer_size);
73100

74-
char *src_buffer_end = src_buffer.get() + src_buffer_size;
75-
char *dst_buffer_end = dst_buffer.get() + dst_buffer_size;
76-
char *src_beg = src_buffer.get() + off_src;
77-
char *dst_beg = dst_buffer.get() + off_dst;
78-
char *src_end = src_beg + capacity;
79-
char *dst_end = dst_beg + capacity;
101+
char *src_buffer_beg = src_buffer.get();
102+
char *src_buffer_end = src_buffer_beg + src_buffer_size;
103+
assert(RoundDown(src_buffer_beg) == src_buffer_beg);
80104

81-
for (int i = 0; i < 35; i++) {
82-
if (poison_src)
83-
__asan_poison_memory_region(src_buffer.get(), src_buffer_size);
84-
if (poison_dst)
85-
__asan_poison_memory_region(dst_buffer.get(), dst_buffer_size);
86-
87-
RandomPoison(src_beg, src_end);
88-
std::deque<int> poison_states = GetPoisonedState(src_beg, src_end);
89-
__sanitizer_copy_contiguous_container_annotations(src_beg, src_end, dst_beg,
90-
dst_end);
91-
92-
// If src_buffer were poisoned, expected state of memory before src_beg
93-
// is undetermined.
94-
// If old buffer were not poisoned, that memory should still be unpoisoned.
95-
char *cur;
96-
if (!poison_src) {
97-
for (cur = src_buffer.get(); cur < src_beg; ++cur) {
98-
assert(!__asan_address_is_poisoned(cur));
99-
}
100-
}
101-
for (size_t i = 0; i < poison_states.size(); ++i) {
102-
assert(__asan_address_is_poisoned(&src_beg[i]) == poison_states[i]);
103-
}
104-
// Memory after src_end should be the same as at the beginning.
105-
for (cur = src_end; cur < src_buffer_end; ++cur) {
106-
assert(__asan_address_is_poisoned(cur) == poison_dst);
107-
}
105+
char *dst_buffer_beg = dst_buffer.get();
106+
char *dst_buffer_end = dst_buffer_beg + dst_buffer_size;
107+
assert(RoundDown(dst_buffer_beg) == dst_buffer_beg);
108108

109-
// If dst_buffer were not poisoned, memory before dst_beg should never
110-
// be poisoned. Otherwise, its state is undetermined.
111-
if (!poison_dst) {
112-
for (cur = dst_buffer.get(); cur < dst_beg; ++cur) {
113-
assert(!__asan_address_is_poisoned(cur));
114-
}
115-
}
109+
for (int i = 0; i < 35; i++) {
110+
RandomPoison(src_buffer_beg, src_buffer_end);
111+
RandomPoison(dst_buffer_beg, dst_buffer_end);
116112

117-
char *next;
118-
for (cur = dst_beg; cur + kGranularity <= dst_end; cur = next) {
119-
next = RoundUp(cur + 1);
120-
size_t unpoisoned = CountUnpoisoned(poison_states, next - cur);
121-
if (unpoisoned > 0) {
122-
assert(!__asan_address_is_poisoned(cur + unpoisoned - 1));
123-
}
124-
if (cur + unpoisoned < next) {
125-
assert(__asan_address_is_poisoned(cur + unpoisoned));
126-
}
127-
}
128-
// [cur; dst_end) is not checked yet.
129-
// If dst_buffer were not poisoned, it cannot be poisoned.
130-
// If dst_buffer were poisoned, it should be same as earlier.
131-
if (cur < dst_end) {
132-
size_t unpoisoned = CountUnpoisoned(poison_states, dst_end - cur);
133-
if (unpoisoned > 0) {
134-
assert(!__asan_address_is_poisoned(cur + unpoisoned - 1));
135-
}
136-
if (cur + unpoisoned < dst_end && poison_dst) {
137-
assert(__asan_address_is_poisoned(cur + unpoisoned));
138-
}
139-
}
140-
// Memory annotations after dst_end should be unchanged.
141-
for (cur = dst_end; cur < dst_buffer_end; ++cur) {
142-
assert(__asan_address_is_poisoned(cur) == poison_dst);
143-
}
113+
Test(capacity, off_src, off_dst, src_buffer_beg, src_buffer_end,
114+
dst_buffer_beg, dst_buffer_end);
144115
}
145116

146-
__asan_unpoison_memory_region(src_buffer.get(), src_buffer_size);
147-
__asan_unpoison_memory_region(dst_buffer.get(), dst_buffer_size);
117+
__asan_unpoison_memory_region(src_buffer_beg, src_buffer_size);
118+
__asan_unpoison_memory_region(dst_buffer_beg, dst_buffer_size);
148119
}
149120

150-
void TestOverlappingContainers(size_t capacity, size_t off_src, size_t off_dst,
151-
bool poison_whole, bool poison_dst) {
152-
size_t buffer_size = capacity + off_src + off_dst + kGranularity * 3;
121+
static void TestOverlappingContainers(size_t capacity, size_t off_src,
122+
size_t off_dst) {
123+
// Test will copy [off_src, off_src + capacity) to [off_dst, off_dst + capacity).
124+
// Allocate buffers to have additional granule before and after tested ranges.
125+
off_src += kGranularity;
126+
off_dst += kGranularity;
127+
size_t buffer_size =
128+
RoundUp(std::max(off_src, off_dst) + capacity) + kGranularity;
153129

154130
// Use unique_ptr with a custom deleter to manage the buffer
155131
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(buffer_size);
156132

157-
char *buffer_end = buffer.get() + buffer_size;
158-
char *src_beg = buffer.get() + kGranularity + off_src;
159-
char *dst_beg = buffer.get() + kGranularity + off_dst;
160-
char *src_end = src_beg + capacity;
161-
char *dst_end = dst_beg + capacity;
133+
char *buffer_beg = buffer.get();
134+
char *buffer_end = buffer_beg + buffer_size;
135+
assert(RoundDown(buffer_beg) == buffer_beg);
162136

163137
for (int i = 0; i < 35; i++) {
164-
if (poison_whole)
165-
__asan_poison_memory_region(buffer.get(), buffer_size);
166-
if (poison_dst)
167-
__asan_poison_memory_region(dst_beg, dst_end - dst_beg);
168-
169-
RandomPoison(src_beg, src_end);
170-
auto poison_states = GetPoisonedState(src_beg, src_end);
171-
__sanitizer_copy_contiguous_container_annotations(src_beg, src_end, dst_beg,
172-
dst_end);
173-
// This variable is used only when buffer ends in the middle of a granule.
174-
bool can_modify_last_granule = __asan_address_is_poisoned(dst_end);
175-
176-
// If whole buffer were poisoned, expected state of memory before first container
177-
// is undetermined.
178-
// If old buffer were not poisoned, that memory should still be unpoisoned.
179-
char *cur;
180-
if (!poison_whole) {
181-
for (cur = buffer.get(); cur < src_beg && cur < dst_beg; ++cur) {
182-
assert(!__asan_address_is_poisoned(cur));
183-
}
184-
}
138+
RandomPoison(buffer_beg, buffer_end);
185139

186-
// Memory after end of both containers should be the same as at the beginning.
187-
for (cur = (src_end > dst_end) ? src_end : dst_end; cur < buffer_end;
188-
++cur) {
189-
assert(__asan_address_is_poisoned(cur) == poison_whole);
190-
}
191-
192-
char *next;
193-
for (cur = dst_beg; cur + kGranularity <= dst_end; cur = next) {
194-
next = RoundUp(cur + 1);
195-
size_t unpoisoned = CountUnpoisoned(poison_states, next - cur);
196-
if (unpoisoned > 0) {
197-
assert(!__asan_address_is_poisoned(cur + unpoisoned - 1));
198-
}
199-
if (cur + unpoisoned < next) {
200-
assert(__asan_address_is_poisoned(cur + unpoisoned));
201-
}
202-
}
203-
// [cur; dst_end) is not checked yet, if container ends in the middle of a granule.
204-
// It can be poisoned, only if non-container bytes in that granule were poisoned.
205-
// Otherwise, it should be unpoisoned.
206-
if (cur < dst_end) {
207-
size_t unpoisoned = CountUnpoisoned(poison_states, dst_end - cur);
208-
if (unpoisoned > 0) {
209-
assert(!__asan_address_is_poisoned(cur + unpoisoned - 1));
210-
}
211-
if (cur + unpoisoned < dst_end && can_modify_last_granule) {
212-
assert(__asan_address_is_poisoned(cur + unpoisoned));
213-
}
214-
}
140+
Test(capacity, off_src, off_dst, buffer_beg, buffer_end, buffer_beg,
141+
buffer_end);
215142
}
216143

217-
__asan_unpoison_memory_region(buffer.get(), buffer_size);
144+
__asan_unpoison_memory_region(buffer_beg, buffer_size);
218145
}
219146

220147
int main(int argc, char **argv) {
221148
int n = argc == 1 ? 64 : atoi(argv[1]);
222-
for (size_t off_src = 0; off_src < kGranularity + 2; off_src++) {
223-
for (size_t off_dst = 0; off_dst < kGranularity + 2; off_dst++) {
149+
for (size_t off_src = 0; off_src < kGranularity; off_src++) {
150+
for (size_t off_dst = 0; off_dst < kGranularity; off_dst++) {
224151
for (int capacity = 0; capacity <= n; capacity++) {
225-
for (int poison_dst = 0; poison_dst < 2; ++poison_dst) {
226-
for (int poison_dst = 0; poison_dst < 2; ++poison_dst) {
227-
TestNonOverlappingContainers(capacity, off_src, off_dst, poison_dst,
228-
poison_dst);
229-
TestOverlappingContainers(capacity, off_src, off_dst, poison_dst,
230-
poison_dst);
231-
}
232-
}
152+
TestNonOverlappingContainers(capacity, off_src, off_dst);
153+
TestOverlappingContainers(capacity, off_src, off_dst);
233154
}
234155
}
235156
}

0 commit comments

Comments
 (0)