diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -295,7 +295,7 @@ do { *__j = _Ops::__iter_move(__k); __j = __k; - _LIBCPP_ASSERT(__k != __leftmost, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__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. *__j = std::move(__t); } @@ -507,7 +507,7 @@ // Not guarded since we know the last element is greater than the pivot. do { ++__first; - _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (!__comp(__pivot, *__first)); } else { while (++__first < __last && !__comp(__pivot, *__first)) { @@ -518,7 +518,7 @@ // It will be always guarded because __introsort will do the median-of-three // before calling this. do { - _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); --__last; } while (__comp(__pivot, *__last)); } @@ -593,7 +593,7 @@ // this. do { ++__first; - _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (__comp(*__first, __pivot)); // Find the last element less than the pivot. @@ -603,7 +603,7 @@ } else { // Guarded. do { - _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); --__last; } while (!__comp(*__last, __pivot)); } @@ -619,10 +619,10 @@ _Ops::iter_swap(__first, __last); do { ++__first; - _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (__comp(*__first, __pivot)); do { - _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); --__last; } while (!__comp(*__last, __pivot)); } @@ -643,14 +643,15 @@ using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; - const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + // TODO(LLVM18): Make __begin const, see https://reviews.llvm.org/D147089#4349748 + _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around const _RandomAccessIterator __end = __last; (void)__end; // value_type __pivot(_Ops::__iter_move(__first)); if (__comp(__pivot, *(__last - difference_type(1)))) { // Guarded. do { ++__first; - _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (!__comp(__pivot, *__first)); } else { while (++__first < __last && !__comp(__pivot, *__first)) { @@ -661,7 +662,7 @@ // It will be always guarded because __introsort will do the // median-of-three before calling this. do { - _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); --__last; } while (__comp(__pivot, *__last)); } @@ -669,10 +670,10 @@ _Ops::iter_swap(__first, __last); do { ++__first; - _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__first != __end, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (!__comp(__pivot, *__first)); do { - _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, is your comparator a valid strict-weak ordering?"); + _LIBCPP_ASSERT(__last != __begin, "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); --__last; } while (__comp(__pivot, *__last)); } diff --git a/libcxx/test/libcxx/algorithms/alg.sorting/assert.sort.invalid_comparator.pass.cpp b/libcxx/test/libcxx/algorithms/alg.sorting/assert.sort.invalid_comparator.pass.cpp --- a/libcxx/test/libcxx/algorithms/alg.sorting/assert.sort.invalid_comparator.pass.cpp +++ b/libcxx/test/libcxx/algorithms/alg.sorting/assert.sort.invalid_comparator.pass.cpp @@ -25,7 +25,7 @@ // a < b implies that !(b < a) // // If this is not satisfied, we have seen issues in the past where the std::sort implementation -// would proceed to do OOB reads. +// would proceed to do OOB reads (rdar://106897934). // When the debug mode is enabled, this test fails because we actually catch that the comparator // is not a strict-weak ordering before we catch that we'd dereference out-of-bounds inside std::sort, @@ -42,12 +42,9 @@ #include #include +#include "bad_comparator_values.h" #include "check_assertion.h" -std::string DATA = -# include "bad_comparator_values.dat" -; - int main(int, char**) { std::map> comparison_results; // terrible for performance, but really convenient for (auto line : std::views::split(DATA, '\n') | std::views::filter([](auto const& line) { return !line.empty(); })) { diff --git a/libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.dat b/libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.h rename from libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.dat rename to libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.h --- a/libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.dat +++ b/libcxx/test/libcxx/algorithms/alg.sorting/bad_comparator_values.h @@ -1,4 +1,17 @@ -R"( +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_LIBCXX_ALGORITHMS_ALG_SORTING_BAD_COMPARATOR_VALUES_H +#define TEST_LIBCXX_ALGORITHMS_ALG_SORTING_BAD_COMPARATOR_VALUES_H + +#include + +inline constexpr std::string_view DATA = R"( 0 0 0 0 1 1 0 2 1 @@ -3480,4 +3493,6 @@ 58 56 1 58 57 1 58 58 0 -)" +)"; + +#endif // TEST_LIBCXX_ALGORITHMS_ALG_SORTING_BAD_COMPARATOR_VALUES_H