[PATCH] libstdc++: Fix ranges::stable_sort handling of null buffer [PR123180]

Jonathan Wakely jwakely@redhat.com
Thu Dec 18 10:46:16 GMT 2025


The logic of the null pointer check got reversed when converting the
std::stable_sort code for ranges::stable_sort.

libstdc++-v3/ChangeLog:

	PR libstdc++/123180
	* include/bits/ranges_algo.h (__stable_sort_fn::operator()): Fix
	sense of null check. Replace typedef with alias-declaration.
	* testsuite/25_algorithms/stable_sort/123180.cc: New test.
---

Tested x86_64-linux.

 libstdc++-v3/include/bits/ranges_algo.h       |  4 +-
 .../25_algorithms/stable_sort/123180.cc       | 66 +++++++++++++++++++
 2 files changed, 68 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index 5c9fe627aee0..92e298633cf4 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -2709,7 +2709,7 @@ namespace ranges
 	    }
 # endif
 
-	    typedef _Temporary_buffer<_Iter, iter_value_t<_Iter>> _TmpBuf;
+	    using _TmpBuf = _Temporary_buffer<_Iter, iter_value_t<_Iter>>;
 	    // __stable_sort_adaptive sorts the range in two halves,
 	    // so the buffer only needs to fit half the range at once.
 	    _TmpBuf __buf(__first, ptrdiff_t((__last - __first + 1) / 2));
@@ -2718,7 +2718,7 @@ namespace ranges
 	      __detail::__stable_sort_adaptive(__first,
 					       __first + _DistanceType(__buf.size()),
 					       __last, __buf.begin(), __comp_proj);
-	    else if (__buf.begin()) [[unlikely]]
+	    else if (__buf.begin() == nullptr) [[unlikely]]
 	      __detail::__inplace_stable_sort(__first, __last, __comp_proj);
 	    else
 	      __detail::__stable_sort_adaptive_resize(__first, __last, __buf.begin(),
diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc
new file mode 100644
index 000000000000..7c56f37142e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc
@@ -0,0 +1,66 @@
+// { dg-do run }
+
+#include <algorithm>
+#include <new>
+#include <cstdlib>
+#include <cstdio>
+
+#if __cplusplus < 201103L
+# define NOEXCEPT throw()
+# define nullptr 0
+# define THROW_BAD_ALLOC throw(std::bad_alloc)
+#else
+# define NOEXCEPT noexcept
+# define THROW_BAD_ALLOC noexcept(false)
+#endif
+
+std::size_t limit = -1u;
+
+void* operator new(std::size_t n, const std::nothrow_t&) NOEXCEPT
+{
+  if (n > limit)
+    return NULL;
+  return std::malloc(n);
+}
+
+void* operator new(std::size_t n) THROW_BAD_ALLOC
+{
+  return std::malloc(n);
+}
+
+void operator delete(void* p) NOEXCEPT { std::free(p); }
+#ifdef __cpp_sized_deallocation
+void operator delete(void* p, std::size_t) NOEXCEPT { std::free(p); }
+#endif
+
+void
+test_stl_algo()
+{
+  int a[] = { 4, 6, 2, 1, 7, 9, 2, 2, 2, 8 };
+  limit = -1u;
+  std::stable_sort(a, a+10); // gets as much memory as it needs
+  limit = 2 * sizeof(int);
+  std::stable_sort(a, a+10); // only gets memory for two ints
+  limit = 0;
+  std::stable_sort(a, a+10); // gets no memory
+}
+
+void
+test_ranges_algo()
+{
+#if __cplusplus >= 202002L
+  int a[] = { 4, 6, 2, 1, 7, 9, 2, 2, 2, 8 };
+  limit = -1u;
+  std::ranges::stable_sort(a); // gets as much memory as it needs
+  limit = 2 * sizeof(int);
+  std::ranges::stable_sort(a); // only gets memory for two ints
+  limit = 0;
+  std::ranges::stable_sort(a); // gets no memory
+#endif
+}
+
+int main()
+{
+  test_stl_algo();
+  test_ranges_algo();
+}
-- 
2.52.0



More information about the Libstdc++ mailing list