[libcxx-commits] [libcxx] 4a652e4 - [libc++][hardening] Categorize more assertions.

Konstantin Varlamov via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jul 24 14:57:47 PDT 2023


Author: varconst
Date: 2023-07-24T14:57:01-07:00
New Revision: 4a652e4a996ff529f6da24097698dc679fd414df

URL: https://github.com/llvm/llvm-project/commit/4a652e4a996ff529f6da24097698dc679fd414df
DIFF: https://github.com/llvm/llvm-project/commit/4a652e4a996ff529f6da24097698dc679fd414df.diff

LOG: [libc++][hardening] Categorize more assertions.

Differential Revision: https://reviews.llvm.org/D155873

Added: 
    

Modified: 
    libcxx/include/__config
    libcxx/include/__hash_table
    libcxx/include/__node_handle
    libcxx/include/__stop_token/intrusive_list_view.h
    libcxx/include/__string/char_traits.h
    libcxx/include/__tree
    libcxx/src/string.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__config b/libcxx/include/__config
index 8d793ad293a1fe..9759d3b9e8e062 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -239,7 +239,6 @@
 // - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and
 //   a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid:
 //   - the sentinel is reachable from the begin iterator;
-//   - TODO(hardening): where applicable, the input range and the output range do not overlap;
 //   - TODO(hardening): both iterators refer to the same container.
 //
 // - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through
@@ -247,6 +246,9 @@
 //   a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like
 //   `optional` and `function` are considered one-element containers for the purposes of this check.
 //
+// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the
+//   given ranges do not overlap.
+//
 // - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure
 //   the containers have compatible allocators.
 //
@@ -279,34 +281,39 @@
 #  if _LIBCPP_ENABLE_HARDENED_MODE
 
 // Enabled checks.
-#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)      _LIBCPP_ASSERT(expression, message)
-#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)        _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)     _LIBCPP_ASSERT(expression, message)
 // Disabled checks.
-#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)   _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_INTERNAL(expression, message)               _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)          _LIBCPP_ASSUME(expression)
+// Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security
+// vulnerability.
+#    define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)   _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)     _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_INTERNAL(expression, message)                 _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)            _LIBCPP_ASSUME(expression)
 
 // Debug mode checks.
 
 #  elif _LIBCPP_ENABLE_DEBUG_MODE
 
 // All checks enabled.
-#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSERT(expression, message)
-#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSERT(expression, message)
-#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSERT(expression, message)
-#    define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSERT(expression, message)
-#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)         _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)      _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)    _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)      _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_INTERNAL(expression, message)                  _LIBCPP_ASSERT(expression, message)
+#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)             _LIBCPP_ASSERT(expression, message)
 
 // Disable all checks if hardening is not enabled.
 
 #  else
 
 // All checks disabled.
-#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
-#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)         _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)      _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)    _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)      _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_INTERNAL(expression, message)                  _LIBCPP_ASSUME(expression)
+#    define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)             _LIBCPP_ASSUME(expression)
 
 #  endif // _LIBCPP_ENABLE_HARDENED_MODE
 // clang-format on

diff  --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index fb85efad025216..2ae7afdc10dea5 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -1109,7 +1109,7 @@ public:
     local_iterator
     begin(size_type __n)
     {
-        _LIBCPP_ASSERT_UNCATEGORIZED(__n < bucket_count(),
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(),
             "unordered container::begin(n) called with n >= bucket_count()");
         return local_iterator(__bucket_list_[__n], __n, bucket_count());
     }
@@ -1118,7 +1118,7 @@ public:
     local_iterator
     end(size_type __n)
     {
-        _LIBCPP_ASSERT_UNCATEGORIZED(__n < bucket_count(),
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(),
             "unordered container::end(n) called with n >= bucket_count()");
         return local_iterator(nullptr, __n, bucket_count());
     }
@@ -1127,7 +1127,7 @@ public:
     const_local_iterator
     cbegin(size_type __n) const
     {
-        _LIBCPP_ASSERT_UNCATEGORIZED(__n < bucket_count(),
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(),
             "unordered container::cbegin(n) called with n >= bucket_count()");
         return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
     }
@@ -1136,7 +1136,7 @@ public:
     const_local_iterator
     cend(size_type __n) const
     {
-        _LIBCPP_ASSERT_UNCATEGORIZED(__n < bucket_count(),
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(),
             "unordered container::cend(n) called with n >= bucket_count()");
         return const_local_iterator(nullptr, __n, bucket_count());
     }
@@ -2223,8 +2223,8 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
 {
     __next_pointer __np = __p.__node_;
-    _LIBCPP_ASSERT_UNCATEGORIZED(__p != end(),
-                                 "unordered container erase(iterator) called with a non-dereferenceable iterator");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(),
+        "unordered container::erase(iterator) called with a non-dereferenceable iterator");
     iterator __r(__np);
     ++__r;
     remove(__p);
@@ -2423,10 +2423,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
   _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
 #endif
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__node_traits::propagate_on_container_swap::value ||
-                                 this->__node_alloc() == __u.__node_alloc(),
-                                 "list::swap: Either propagate_on_container_swap must be true"
-                                 " or the allocators must compare equal");
+    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__node_traits::propagate_on_container_swap::value ||
+                                        this->__node_alloc() == __u.__node_alloc(),
+                                        "unordered container::swap: Either propagate_on_container_swap "
+                                        "must be true or the allocators must compare equal");
     {
     __node_pointer_pointer __npp = __bucket_list_.release();
     __bucket_list_.reset(__u.__bucket_list_.release());
@@ -2451,7 +2451,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__n < bucket_count(),
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(),
         "unordered container::bucket_size(n) called with n >= bucket_count()");
     __next_pointer __np = __bucket_list_[__n];
     size_type __bc = bucket_count();

diff  --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle
index 17a9589e2fbc80..cc4eaf73c0bbea 100644
--- a/libcxx/include/__node_handle
+++ b/libcxx/include/__node_handle
@@ -149,7 +149,7 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     __basic_node_handle& operator=(__basic_node_handle&& __other)
     {
-        _LIBCPP_ASSERT_UNCATEGORIZED(
+        _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
             __alloc_ == _VSTD::nullopt ||
             __alloc_traits::propagate_on_container_move_assignment::value ||
             __alloc_ == __other.__alloc_,

diff  --git a/libcxx/include/__stop_token/intrusive_list_view.h b/libcxx/include/__stop_token/intrusive_list_view.h
index 4b63955e0d13cc..11a3e267e7c6d6 100644
--- a/libcxx/include/__stop_token/intrusive_list_view.h
+++ b/libcxx/include/__stop_token/intrusive_list_view.h
@@ -67,7 +67,7 @@ struct __intrusive_list_view {
         __node->__next_->__prev_ = __node->__prev_;
       }
     } else {
-      _LIBCPP_ASSERT_UNCATEGORIZED(__node == __head_, "Node to be removed has no prev node, so it has to be the head");
+      _LIBCPP_ASSERT_INTERNAL(__node == __head_, "Node to be removed has no prev node, so it has to be the head");
       __pop_front();
     }
   }

diff  --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index e42347488d37bb..c201fc9a1cda77 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -142,7 +142,8 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha
     static _LIBCPP_CONSTEXPR_SINCE_CXX20
     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) {
         if (!__libcpp_is_constant_evaluated()) {
-            _LIBCPP_ASSERT_UNCATEGORIZED(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+            _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
+                __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
         }
         char_type* __r = __s1;
         for (; __n; --__n, ++__s1, ++__s2)
@@ -236,7 +237,8 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
     static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
         if (!__libcpp_is_constant_evaluated())
-            _LIBCPP_ASSERT_UNCATEGORIZED(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+            _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
+                __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
         std::copy_n(__s2, __n, __s1);
         return __s1;
     }
@@ -307,7 +309,8 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
     static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
         if (!__libcpp_is_constant_evaluated())
-            _LIBCPP_ASSERT_UNCATEGORIZED(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+            _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
+                __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
         std::copy_n(__s2, __n, __s1);
         return __s1;
     }
@@ -371,7 +374,8 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
     static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
         if (!__libcpp_is_constant_evaluated())
-            _LIBCPP_ASSERT_UNCATEGORIZED(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+            _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
+                __s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
         std::copy_n(__s2, __n, __s1);
         return __s1;
     }
@@ -455,7 +459,8 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
     static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
         if (!__libcpp_is_constant_evaluated())
-            _LIBCPP_ASSERT_UNCATEGORIZED(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+            _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
+                __s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
         std::copy_n(__s2, __n, __s1);
         return __s1;
     }

diff  --git a/libcxx/include/__tree b/libcxx/include/__tree
index 92b5e65e115827..58d4a97c04035a 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -168,7 +168,7 @@ inline _LIBCPP_INLINE_VISIBILITY
 _NodePtr
 __tree_min(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "Root node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null");
     while (__x->__left_ != nullptr)
         __x = __x->__left_;
     return __x;
@@ -180,7 +180,7 @@ inline _LIBCPP_INLINE_VISIBILITY
 _NodePtr
 __tree_max(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "Root node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null");
     while (__x->__right_ != nullptr)
         __x = __x->__right_;
     return __x;
@@ -191,7 +191,7 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI _NodePtr
 __tree_next(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
     if (__x->__right_ != nullptr)
         return _VSTD::__tree_min(__x->__right_);
     while (!_VSTD::__tree_is_left_child(__x))
@@ -204,7 +204,7 @@ inline _LIBCPP_INLINE_VISIBILITY
 _EndNodePtr
 __tree_next_iter(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
     if (__x->__right_ != nullptr)
         return static_cast<_EndNodePtr>(_VSTD::__tree_min(__x->__right_));
     while (!_VSTD::__tree_is_left_child(__x))
@@ -219,7 +219,7 @@ inline _LIBCPP_INLINE_VISIBILITY
 _NodePtr
 __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
     if (__x->__left_ != nullptr)
         return _VSTD::__tree_max(__x->__left_);
     _NodePtr __xx = static_cast<_NodePtr>(__x);
@@ -233,7 +233,7 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI _NodePtr
 __tree_leaf(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
     while (true)
     {
         if (__x->__left_ != nullptr)
@@ -257,8 +257,8 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI void
 __tree_left_rotate(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x->__right_ != nullptr, "node should have a right child");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x->__right_ != nullptr, "node should have a right child");
     _NodePtr __y = __x->__right_;
     __x->__right_ = __y->__left_;
     if (__x->__right_ != nullptr)
@@ -278,8 +278,8 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI void
 __tree_right_rotate(_NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "node shouldn't be null");
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x->__left_ != nullptr, "node should have a left child");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x->__left_ != nullptr, "node should have a left child");
     _NodePtr __y = __x->__left_;
     __x->__left_ = __y->__right_;
     if (__x->__left_ != nullptr)
@@ -304,8 +304,8 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI void
 __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__root != nullptr, "Root of the tree shouldn't be null");
-    _LIBCPP_ASSERT_UNCATEGORIZED(__x != nullptr, "Can't attach null node to a leaf");
+    _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be null");
+    _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf");
     __x->__is_black_ = __x == __root;
     while (__x != __root && !__x->__parent_unsafe()->__is_black_)
     {
@@ -374,8 +374,8 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI void
 __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
 {
-    _LIBCPP_ASSERT_UNCATEGORIZED(__root != nullptr, "Root node should not be null");
-    _LIBCPP_ASSERT_UNCATEGORIZED(__z != nullptr, "The node to remove should not be null");
+    _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null");
+    _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be null");
     _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants should hold");
     // __z will be removed from the tree.  Client still needs to destruct/deallocate it
     // __y is either __z, or if __z has two children, __tree_next(__z).

diff  --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp
index 3d671bccdc6e0b..4f3de555e3a903 100644
--- a/libcxx/src/string.cpp
+++ b/libcxx/src/string.cpp
@@ -346,7 +346,7 @@ S i_to_string(V v) {
     constexpr size_t bufsize = numeric_limits<V>::digits10 + 2;  // +1 for minus, +1 for digits10
     char buf[bufsize];
     const auto res = to_chars(buf, buf + bufsize, v);
-    _LIBCPP_ASSERT_UNCATEGORIZED(res.ec == errc(), "bufsize must be large enough to accomodate the value");
+    _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value");
     return S(buf, res.ptr);
 }
 


        


More information about the libcxx-commits mailing list