[gcc r16-8392] libstdc++: [_GLIBCXX_DEBUG] Fix COW string valid range check

Francois Dumont fdumont@gcc.gnu.org
Wed Apr 1 16:59:53 GMT 2026


https://gcc.gnu.org/g:c0b659db1adcf84c04629cd8aeda89f1d2047e2a

commit r16-8392-gc0b659db1adcf84c04629cd8aeda89f1d2047e2a
Author: François Dumont <frs.dumont@gmail.com>
Date:   Mon Mar 30 22:18:50 2026 +0200

    libstdc++: [_GLIBCXX_DEBUG] Fix COW string valid range check
    
    In revision 698a6af5dcbae5d935bcda8a461dea8458c658dc the _GLIBCXX_DEBUG code
    for the Library Defect 438 has been removed as starting in C++11 the iterator
    type is constrained through the _RequireInputIter requirement.
    
    But the COW basic_string implementation used when _GLIBCXX_USE_CXX11_ABI=0 is
    missing the _RequireInputIter constraint on a number of methods resulting in test
    failures.
    
    For the moment move the culprit __glibcxx_requires_valid_range call in the COW
    basic_string implementation in a method where the iterator type has already been
    checked.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/cow_string.h
            (basic_string::replace(iterator, iterator, _InputIte, _InputIte)): Move
            __glibcxx_requires_valid_range to...
            (basic_string::_M_replace_dispatch(iterator, iterator, _InputIte,
            _InputIte, __fase_type)): ...here.
            * testsuite/21_strings/basic_string/debug/append_neg.cc: New test case.
            * testsuite/21_strings/basic_string/debug/assign_neg.cc: New test case.
            * testsuite/21_strings/basic_string/debug/construct_neg.cc: New test case.
            * testsuite/21_strings/basic_string/debug/insert_neg.cc: New test case.
            * testsuite/21_strings/basic_string/debug/replace_neg.cc: New test case.
    
    Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/cow_string.h               |  2 +-
 .../21_strings/basic_string/debug/append_neg.cc      | 19 +++++++++++++++++++
 .../21_strings/basic_string/debug/assign_neg.cc      | 19 +++++++++++++++++++
 .../21_strings/basic_string/debug/construct_neg.cc   | 17 +++++++++++++++++
 .../21_strings/basic_string/debug/insert_neg.cc      | 19 +++++++++++++++++++
 .../21_strings/basic_string/debug/replace_neg.cc     | 20 ++++++++++++++++++++
 6 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index 6cf002243729..df71185e556d 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -2124,7 +2124,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{
 	  _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
 				   && __i2 <= _M_iend());
-	  __glibcxx_requires_valid_range(__k1, __k2);
 	  typedef typename std::__is_integer<_InputIterator>::__type _Integral;
 	  return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
 	}
@@ -3833,6 +3832,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
 			  _InputIterator __k2, __false_type)
       {
+	__glibcxx_requires_valid_range(__k1, __k2);
 	const basic_string __s(__k1, __k2);
 	const size_type __n1 = __i2 - __i1;
 	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/append_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/append_neg.cc
new file mode 100644
index 000000000000..befe83a84f35
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/append_neg.cc
@@ -0,0 +1,19 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <string>
+
+void test01()
+{
+  std::vector<char> v1(10, 'a');
+  std::string s2;
+
+  s2.append(v1.begin() + 7, v1.begin() + 2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/assign_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/assign_neg.cc
new file mode 100644
index 000000000000..5f32c170f504
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/assign_neg.cc
@@ -0,0 +1,19 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <string>
+
+void test01()
+{
+  std::vector<char> v1(10, 'a');
+  std::string s2;
+
+  s2.assign(v1.begin() + 7, v1.begin() + 2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/construct_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/construct_neg.cc
new file mode 100644
index 000000000000..1ac933d43091
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/construct_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <string>
+
+void test01()
+{
+  std::vector<char> v1(10, 'a');
+  std::string s2(v1.begin() + 7, v1.begin() + 2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/insert_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/insert_neg.cc
new file mode 100644
index 000000000000..95530ef2a510
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/insert_neg.cc
@@ -0,0 +1,19 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <string>
+
+void test01()
+{
+  std::vector<char> v1(10, 'a');
+  std::string s2;
+
+  s2.insert(s2.begin(), v1.begin() + 7, v1.begin() + 2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/replace_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/replace_neg.cc
new file mode 100644
index 000000000000..fd3df9e8539e
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/replace_neg.cc
@@ -0,0 +1,20 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <string>
+
+void test01()
+{
+  std::vector<char> v1(10, 'a');
+  std::string s2 = "bbbbbbbbbb";
+
+  s2.replace(s2.begin(), s2.begin() + 5,
+	     v1.begin() + 7, v1.begin() + 2);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}


More information about the Libstdc++-cvs mailing list