Issue |
146106
|
Summary |
[asan] Clarify how __sanitizer_annotate_contiguous_container works
|
Labels |
libc++,
compiler-rt:asan
|
Assignees |
|
Reporter |
ldionne
|
I was looking at libc++'s implementation of container ASAN annotations and I couldn't understand how `__sanitizer_annotate_contiguous_container` works. The documentation [here](https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/sanitizer/common_interface_defs.h#L113-L159) says:
```
// This annotation tells the Sanitizer tool about the current state of the
/// container so that the tool can report errors when memory from
/// [mid, end) is accessed. Insert this annotation into methods like
/// push_back() or pop_back(). Supply the old and new values of
/// mid(old_mid and new_mid). In the initial
/// state mid == end, so that should be the final state when the
/// container is destroyed or when the container reallocates the storage.
```
This says that `[mid, end)` is the range considered invalid to access, which makes sense. However it also says that the initial state is `mid == end`, which means that the whole range `[begin, mid) == [begin, end)` is considered valid to access. Shouldn't the initial state be that `mid == begin` instead, so that the range `[mid, end) == the whole vector` be considered invalid to access?
This also ties into a question I have about our usage in libc++ (CC @AdvenamTacet):
```c++
template <class _Tp, class _Allocator>
void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
__annotate_delete();
auto __new_begin = __v.__begin_ - (__end_ - __begin_);
std::__uninitialized_allocator_relocate(__alloc_, __begin_, __end_, __new_begin);
__v.__begin_ = __new_begin;
__end_ = __begin_; // All the objects have been destroyed by relocating them.
std::swap(this->__begin_, __v.__begin_);
std::swap(this->__end_, __v.__end_);
std::swap(this->__cap_, __v.__cap_);
__v.__first_ = __v.__begin_;
__annotate_new(size());
}
```
`__annotate_delete()` basically calls
```
__sanitizer_annotate_contiguous_container(data(), data() + capacity(),
data() + size(), data() + capacity());
```
If I understand correctly, this sets the sanitizer state to this (using the `beg` `end` `mid` terminology from the sanitizer documentation, not the terminology inside `std::vector`):
- `beg == data()`
- `end == data() + capacity()`
- `mid == data() + capacity()`
This means that after calling `__annotate_delete()`, ASAN would consider the range `[mid, end) == [data() + capacity(), data() + capacity) == empty-range` as invalid. Is that intended? Is the goal to mark the whole range as accessible so we can then touch it (in `__uninitialized_allocator_relocate`) without triggering an ASAN violation?
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs