[llvm-branch-commits] [libcxx] release/18.x: [libcxx] Align `__recommend() + 1` by __endian_factor (#90292) (PR #95264)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jun 15 10:21:42 PDT 2024


https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/95264

>From 72c9425a79fda8e9001fcde091e8703f9fb2a43a Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 24 Jan 2024 09:28:58 -0500
Subject: [PATCH 1/2] [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.

(cherry picked from commit 382f70a877f00ab71f3cb5ba461b52e1b59cd292)
---
 libcxx/include/string | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index ba169c3dbfc9e..618ceb71b26b4 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1943,8 +1943,8 @@ 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) : 1;
+    size_type __guess          = __align_it<__boundary>(__s + 1) - 1;
     if (__guess == __min_cap)
       ++__guess;
     return __guess;

>From 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 2 May 2024 14:26:38 -0700
Subject: [PATCH 2/2] [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`)

(cherry picked from commit d129ea8d2fa347e63deec0791faf389b84f20ce1)
---
 libcxx/include/string | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 618ceb71b26b4..56e2ef09947f4 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1943,10 +1943,10 @@ private:
     if (__s < __min_cap) {
       return static_cast<size_type>(__min_cap) - 1;
     }
-    const size_type __boundary = sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : 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;
   }
 



More information about the llvm-branch-commits mailing list