Skip to content

[libc++][hardening] Categorize assertions related to strict weak ordering #77405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions libcxx/include/__algorithm/comp_ref_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct __debug_less {
_LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI decltype((void)std::declval<_Compare&>()(
std::declval<_LHS&>(), std::declval<_RHS&>()))
__do_compare_assert(int, _LHS& __l, _RHS& __r) {
_LIBCPP_ASSERT_UNCATEGORIZED(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering");
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering");
(void)__l;
(void)__r;
}
Expand All @@ -53,8 +53,7 @@ struct __debug_less {
_LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI void __do_compare_assert(long, _LHS&, _RHS&) {}
};

// Pass the comparator by lvalue reference. Or in debug mode, using a
// debugging wrapper that stores a reference.
// Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference.
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
template <class _Comp>
using __comp_ref_type = __debug_less<_Comp>;
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/__algorithm/nth_element.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ __nth_element(
while (true) {
while (!__comp(*__first, *__i)) {
++__i;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__i != __last,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
}
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__j != __first,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__j;
Expand Down Expand Up @@ -150,13 +150,13 @@ __nth_element(
// __m still guards upward moving __i
while (__comp(*__i, *__m)) {
++__i;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__i != __last,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
}
// It is now known that a guard exists for downward moving __j
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__j != __first,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__j;
Expand Down
22 changes: 11 additions & 11 deletions libcxx/include/__algorithm/sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ __insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIte
do {
*__j = _Ops::__iter_move(__k);
__j = __k;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__k != __leftmost,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above.
Expand Down Expand Up @@ -544,7 +544,7 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last,
// Not guarded since we know the last element is greater than the pivot.
do {
++__first;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__first != __end,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (!__comp(__pivot, *__first));
Expand All @@ -557,7 +557,7 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last,
// It will be always guarded because __introsort will do the median-of-three
// before calling this.
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__last != __begin,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__last;
Expand Down Expand Up @@ -635,7 +635,7 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte
// this.
do {
++__first;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__first != __end,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (__comp(*__first, __pivot));
Expand All @@ -647,7 +647,7 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte
} else {
// Guarded.
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__last != __begin,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__last;
Expand All @@ -665,12 +665,12 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte
_Ops::iter_swap(__first, __last);
do {
++__first;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__first != __end,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (__comp(*__first, __pivot));
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__last != __begin,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__last;
Expand Down Expand Up @@ -702,7 +702,7 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter
// Guarded.
do {
++__first;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__first != __end,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (!__comp(__pivot, *__first));
Expand All @@ -715,7 +715,7 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter
// It will be always guarded because __introsort will do the
// median-of-three before calling this.
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__last != __begin,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__last;
Expand All @@ -725,12 +725,12 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter
_Ops::iter_swap(__first, __last);
do {
++__first;
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__first != __end,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
} while (!__comp(__pivot, *__first));
do {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__last != __begin,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__last;
Expand Down
6 changes: 3 additions & 3 deletions libcxx/include/__algorithm/three_way_comp_ref_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ struct __debug_three_way_comp {
__expected = _Order::greater;
if (__o == _Order::greater)
__expected = _Order::less;
_LIBCPP_ASSERT_UNCATEGORIZED(__comp_(__l, __r) == __expected, "Comparator does not induce a strict weak ordering");
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
__comp_(__l, __r) == __expected, "Comparator does not induce a strict weak ordering");
(void)__l;
(void)__r;
}
};

// Pass the comparator by lvalue reference. Or in debug mode, using a
// debugging wrapper that stores a reference.
// Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference.
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
template <class _Comp>
using __three_way_comp_ref_type = __debug_three_way_comp<_Comp>;
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@
// - `_LIBCPP_ASSERT_PEDANTIC` -- checks prerequisites which are imposed by the Standard, but violating which happens to
// be benign in our implementation.
//
// - `_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT` -- checks that the given argument satisfies the semantic requirements imposed
// by the Standard. Typically, there is no simple way to completely prove that a semantic requirement is satisfied;
// thus, this would often be a heuristic check and it might be quite expensive.
//
// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on
// user input.
//
Expand Down Expand Up @@ -359,6 +363,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)

Expand All @@ -378,6 +383,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSERT(expression, message)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message)
// Disabled checks.
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)

// Debug hardening mode checks.
Expand All @@ -394,6 +400,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSERT(expression, message)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSERT(expression, message)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(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)

Expand All @@ -411,6 +418,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)

Expand Down
14 changes: 7 additions & 7 deletions libcxx/include/__debug_utils/strict_weak_ordering_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _RandomAccessIterator, class _Comp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
#ifdef _LIBCPP_DEBUG_STRICT_WEAK_ORDERING_CHECK
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
using __diff_t = __iter_diff_t<_RandomAccessIterator>;
using _Comp_ref = __comp_ref_type<_Comp>;
if (!__libcpp_is_constant_evaluated()) {
// Check if the range is actually sorted.
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
(std::is_sorted<_RandomAccessIterator, _Comp_ref>(__first, __last, _Comp_ref(__comp))),
"The range is not sorted after the sort, your comparator is not a valid strict-weak ordering");
// Limit the number of elements we need to check.
Expand All @@ -46,18 +46,18 @@ __check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccess
// Check that the elements from __p to __q are equal between each other.
for (__diff_t __b = __p; __b < __q; ++__b) {
for (__diff_t __a = __p; __a <= __b; ++__a) {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
!__comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering");
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
!__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering");
}
}
// Check that elements between __p and __q are less than between __q and __size.
for (__diff_t __a = __p; __a < __q; ++__a) {
for (__diff_t __b = __q; __b < __size; ++__b) {
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
__comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering");
_LIBCPP_ASSERT_UNCATEGORIZED(
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
!__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering");
}
}
Expand All @@ -69,7 +69,7 @@ __check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccess
(void)__first;
(void)__last;
(void)__comp;
#endif
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
Loading