diff --git a/compiler-rt/test/asan/TestCases/contiguous_container.cpp b/compiler-rt/test/asan/TestCases/contiguous_container.cpp --- a/compiler-rt/test/asan/TestCases/contiguous_container.cpp +++ b/compiler-rt/test/asan/TestCases/contiguous_container.cpp @@ -79,6 +79,95 @@ delete[] buffer; } +void TestDoubleEndedContainerNew(size_t capacity, size_t off_begin, + bool poison_buffer) { + size_t buffer_size = capacity + off_begin + kGranularity * 2; + char *buffer = new char[buffer_size]; + if (poison_buffer) + __asan_poison_memory_region(buffer, buffer_size); + char *st_beg = buffer + off_begin; + char *st_end = st_beg + capacity; + char *beg = st_beg; + char *end = poison_buffer ? st_beg : st_end; + + for (int i = 0; i < 1000; i++) { + size_t size = rand() % (capacity + 1); + size_t skipped = rand() % (capacity - size + 1); + assert(size <= capacity); + char *old_beg = beg; + char *old_end = end; + beg = st_beg + skipped; + end = beg + size; + + __sanitizer_annotate_double_ended_contiguous_container( + st_beg, st_end, old_beg, old_end, beg, end); + + char *cur = buffer; + for (; cur < buffer + RoundDown(off_begin); ++cur) + assert(__asan_address_is_poisoned(cur) == poison_buffer); + // The prefix of the first incomplete granule can switch from poisoned to + // unpoisoned but not otherwise. + for (; cur < buffer + off_begin; ++cur) + assert(poison_buffer || !__asan_address_is_poisoned(cur)); + for (; cur < beg; ++cur) + assert(__asan_address_is_poisoned(cur)); + for (; cur < end; ++cur) + assert(!__asan_address_is_poisoned(cur)); + for (; cur < RoundDown(st_end); ++cur) + assert(__asan_address_is_poisoned(cur)); + // The suffix of the last incomplete granule must be poisoned the same as + // bytes after the end. + for (; cur != st_end + kGranularity; ++cur) { + if (!__asan_address_is_poisoned(cur) == poison_buffer) { + fprintf(stderr, "st_beg:%p, st_end:%p, cur:%p, beg:%p, end:%p\n", + st_beg, st_end, cur, beg, end); + fflush(stderr); + } + assert(__asan_address_is_poisoned(cur) == poison_buffer); + } + } + + for (int i = 0; 0 && i <= capacity; i++) { + for (int j = i; j <= capacity; j++) { + char *old_beg = beg; + char *old_end = end; + beg = st_beg + i; + end = st_beg + j; + __sanitizer_annotate_double_ended_contiguous_container( + st_beg, st_end, old_beg, old_end, beg, end); + + for (char *cur = std::max(st_beg, st_end - 2 * kGranularity); + cur <= std::min(st_end, end + 2 * kGranularity); ++cur) { + if (cur == end || + // Any end in the last unaligned granule is OK, if bytes after the + // storage are not poisoned. + (!poison_buffer && RoundDown(st_end) <= std::min(cur, end))) { + assert(__sanitizer_verify_double_ended_contiguous_container( + st_beg, beg, cur, st_end)); + assert(NULL == + __sanitizer_double_ended_contiguous_container_find_bad_address( + st_beg, beg, cur, st_end)); + } else if (cur < end) { + assert(!__sanitizer_verify_double_ended_contiguous_container( + st_beg, beg, cur, st_end)); + assert(cur == + __sanitizer_double_ended_contiguous_container_find_bad_address( + st_beg, beg, cur, st_end)); + } else { + assert(!__sanitizer_verify_double_ended_contiguous_container( + st_beg, beg, cur, st_end)); + assert(end == + __sanitizer_double_ended_contiguous_container_find_bad_address( + st_beg, beg, cur, st_end)); + } + } + } + } + + __asan_unpoison_memory_region(buffer, buffer_size); + delete[] buffer; +} + void TestDoubleEndedContainer(size_t capacity) { char *st_beg = new char[capacity]; char *st_end = st_beg + capacity; @@ -142,6 +231,7 @@ } } TestDoubleEndedContainer(i); + TestDoubleEndedContainerNew(i, 0, false); } TestThrow(); }