git: 55c5dad2f305 - stable/14 - Merge commit 382f70a877f0 from llvm-project (by Louis Dionne):

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Mon, 10 Jun 2024 07:29:41 UTC
The branch stable/14 has been updated by dim:

URL: https://cgit.FreeBSD.org/src/commit/?id=55c5dad2f305f74d1ff5ca85c453635511aab9b2

commit 55c5dad2f305f74d1ff5ca85c453635511aab9b2
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2024-06-07 18:42:53 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2024-06-10 07:29:25 +0000

    Merge commit 382f70a877f0 from llvm-project (by Louis Dionne):
    
      [libc++][NFC] Rewrite function call on two lines for clarity (#79141)
    
      Previously, there was a ternary conditional with a less-than comparison
      appearing inside a template argument, which was really confusing because
      of the <...> of the function template. This patch rewrites the same
      statement on two lines for clarity.
    
    Merge commit d129ea8d2fa3 from llvm-project (by Vitaly Buka):
    
      [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`)
    
    This should fix incorrect deallocation sizes for some instances of
    std::string. Memory profiling or debugging tools like AddressSanitizer,
    LeakSanitizer or TCMalloc could then complain about the the size passed
    to a deallocation not matching the size originally passed to the
    allocation.
    
    Reported by:    Aliaksei Kandratsenka <alkondratenko@gmail.com>
    PR:             279560
    MFC after:      3 days
    
    (cherry picked from commit ead8e4c081e5c4de4d508fc353f381457b058ca6)
---
 contrib/llvm-project/libcxx/include/string | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/contrib/llvm-project/libcxx/include/string b/contrib/llvm-project/libcxx/include/string
index ba169c3dbfc9..56e2ef09947f 100644
--- a/contrib/llvm-project/libcxx/include/string
+++ b/contrib/llvm-project/libcxx/include/string
@@ -1943,10 +1943,10 @@ private:
     if (__s < __min_cap) {
       return static_cast<size_type>(__min_cap) - 1;
     }
-    size_type __guess =
-        __align_it < sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : 1 > (__s + 1) - 1;
+    const size_type __boundary = sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : __endian_factor;
+    size_type __guess          = __align_it<__boundary>(__s + 1) - 1;
     if (__guess == __min_cap)
-      ++__guess;
+      __guess += __endian_factor;
     return __guess;
   }