[libcxx-commits] [libcxx] [libc++] Fix size_t overflow in make_shared<T[]> and allocate_shared<T[]> (PR #223735)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 16 02:45:45 PDT 2026


================
@@ -738,17 +739,28 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count {
 
   // Returns the number of bytes required to store a control block followed by the given number
   // of elements of _Tp, with the whole storage being aligned to a multiple of _Tp's alignment.
+  //
+  // Throws std::bad_array_new_length if that number of bytes is not representable as a size_t.
   _LIBCPP_HIDE_FROM_ABI static constexpr size_t __bytes_for(size_t __elements) {
+    constexpr size_t __align = alignof(__unbounded_array_control_block);
+
     // When there's 0 elements, the control block alone is enough since it holds one element.
     // Otherwise, we allocate one fewer element than requested because the control block already
-    // holds one. Also, we use the bitwise formula below to ensure that we allocate enough bytes
-    // for the whole allocation to be a multiple of _Tp's alignment. That formula is taken from [1].
+    // holds one.
+    size_t __bytes = sizeof(__unbounded_array_control_block);
+    if (__elements != 0) {
+      if (__builtin_mul_overflow(__elements - 1, sizeof(_Tp), &__bytes) ||
+          __builtin_add_overflow(__bytes, sizeof(__unbounded_array_control_block), &__bytes))
+        std::__throw_bad_array_new_length();
----------------
philnik777 wrote:

`__builtin_mul_overflow` + `__builtin_add_overflow` seems to be an _incredibly_ common pattern. 3 out of 4 current uses of `__builtin_add_overflow` are that pattern and the last one is `saturating_add`. Should we maybe introduce a `__checked_mul_add(__elements - 1, sizeof(_Tp), sizeof(__unbounded_array_control_block))`?

https://github.com/llvm/llvm-project/pull/223735


More information about the libcxx-commits mailing list