Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libcxx] Align
__recommend() + 1
by __endian_factor (#90292)
This is detected by asan after #83774 Allocation size will be divided by `__endian_factor` before storing. If it's not aligned, we will not be able to recover allocation size to pass into `__alloc_traits::deallocate`. we have code like this ``` auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __set_long_cap(__allocation.count); void __set_long_cap(size_type __s) _NOEXCEPT { __r_.first().__l.__cap_ = __s / __endian_factor; __r_.first().__l.__is_long_ = true; } size_type __get_long_cap() const _NOEXCEPT { return __r_.first().__l.__cap_ * __endian_factor; } inline ~basic_string() { __annotate_delete(); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } ``` 1. __recommend() -> even size 2. `std::__allocate_at_least(__alloc(), __recommend(__sz) + 1)` - > not even size 3. ` __set_long_cap() `- > lose one bit of size for __endian_factor == 2 (see `/ __endian_factor`) 4. `__alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap())` -> uses even size (see `__get_long_cap`)
- Loading branch information
d129ea8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any particular string length that triggers this mismatch?
I added sized delete mismatch checking to Valgrind about 4 years ago and I've almost never seen a real problem in the wild (the only case I know of is if you wirite a derived class that has some virtual functions but not a virtual destructor then deleting through a base class can result in a size mismatch).
d129ea8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We detected this with strings that were 23 chars excluding NUL, which __recommend rounds to 24, gets +1'd to 25, and then deallocate gets passed 24.
d129ea8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems I missed the boat on this one. It's already patched in FreeBSD base and never showed up on my Valgrind radar.