public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r11-10125] libstdc++: Fix std::regex_replace for strings with embedded null [PR103664]
Date: Thu,  7 Jul 2022 23:32:49 +0000 (GMT)	[thread overview]
Message-ID: <20220707233249.EBEF7384A893@sourceware.org> (raw)

https://gcc.gnu.org/g:8bee3c458ec14ca3e3a429a08694740a894e0c96

commit r11-10125-g8bee3c458ec14ca3e3a429a08694740a894e0c96
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Sun Dec 12 21:15:17 2021 +0000

    libstdc++: Fix std::regex_replace for strings with embedded null [PR103664]
    
    The overload of std::regex_replace that takes a std::basic_string as the
    fmt argument (for the replacement string) is implemented in terms of the
    one taking a const C*, which uses std::char_traits to find the length.
    That means it stops at a null character, even though the basic_string
    might have additional characters beyond that.
    
    Rather than duplicate the implementation of the const C* one for the
    std::basic_string case, this moves that implementation to a new
    __regex_replace function which takes a const C* and a length. Then both
    the std::basic_string and const C* overloads can call that (with the
    latter using char_traits to find the length to pass to the new
    function).
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/103664
            * include/bits/regex.h (__regex_replace): Declare.
            (regex_replace): Use it.
            * include/bits/regex.tcc (__regex_replace): Replace regex_replace
            definition with __regex_replace.
            * testsuite/28_regex/algorithms/regex_replace/char/103664.cc: New test.
    
    (cherry picked from commit ef5d671cd80a4afa4f74c3dfe2904c63f51fcfde)

Diff:
---
 libstdc++-v3/include/bits/regex.h                    | 20 ++++++++++++++++++--
 libstdc++-v3/include/bits/regex.tcc                  |  9 ++++-----
 .../28_regex/algorithms/regex_replace/char/103664.cc | 11 +++++++++++
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index 1ae089c351f..e35b9b06286 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -2462,6 +2462,15 @@ _GLIBCXX_END_NAMESPACE_CXX11
 		 = regex_constants::match_default) = delete;
 
   // std [28.11.4] Function template regex_replace
+
+  template<typename _Out_iter, typename _Bi_iter,
+	   typename _Rx_traits, typename _Ch_type>
+    _Out_iter
+    __regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
+		    const basic_regex<_Ch_type, _Rx_traits>& __e,
+		    const _Ch_type* __fmt, size_t __len,
+		    regex_constants::match_flag_type __flags);
+
   /**
    * @brief Search for a regular expression within a range for multiple times,
    and replace the matched parts through filling a format string.
@@ -2485,7 +2494,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
 		  regex_constants::match_flag_type __flags
 		  = regex_constants::match_default)
     {
-      return regex_replace(__out, __first, __last, __e, __fmt.c_str(), __flags);
+      return std::__regex_replace(__out, __first, __last, __e, __fmt.c_str(),
+				  __fmt.length(), __flags);
     }
 
   /**
@@ -2508,7 +2518,13 @@ _GLIBCXX_END_NAMESPACE_CXX11
 		  const basic_regex<_Ch_type, _Rx_traits>& __e,
 		  const _Ch_type* __fmt,
 		  regex_constants::match_flag_type __flags
-		  = regex_constants::match_default);
+		  = regex_constants::match_default)
+    {
+      return std::__regex_replace(__out, __first, __last, __e, __fmt,
+				  char_traits<_Ch_type>::length(__fmt),
+				  __flags);
+    }
+
 
   /**
    * @brief Search for a regular expression within a string for multiple times,
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index 39ad3f0a4cc..ef152851e55 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -461,10 +461,10 @@ namespace __detail
   template<typename _Out_iter, typename _Bi_iter,
 	   typename _Rx_traits, typename _Ch_type>
     _Out_iter
-    regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
-		  const basic_regex<_Ch_type, _Rx_traits>& __e,
-		  const _Ch_type* __fmt,
-		  regex_constants::match_flag_type __flags)
+    __regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
+		    const basic_regex<_Ch_type, _Rx_traits>& __e,
+		    const _Ch_type* __fmt, size_t __len,
+		    regex_constants::match_flag_type __flags)
     {
       typedef regex_iterator<_Bi_iter, _Ch_type, _Rx_traits> _IterT;
       _IterT __i(__first, __last, __e, __flags);
@@ -477,7 +477,6 @@ namespace __detail
       else
 	{
 	  sub_match<_Bi_iter> __last;
-	  auto __len = char_traits<_Ch_type>::length(__fmt);
 	  for (; __i != __end; ++__i)
 	    {
 	      if (!(__flags & regex_constants::format_no_copy))
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/103664.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/103664.cc
new file mode 100644
index 00000000000..ca75e49ed3e
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/103664.cc
@@ -0,0 +1,11 @@
+// { dg-do run { target c++11 } }
+
+#include <regex>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // PR libstdc++/103664
+  std::string a = regex_replace("123", std::regex("2"), std::string("a\0b", 3));
+  VERIFY( a == std::string("1a\0b3", 5) );
+}


                 reply	other threads:[~2022-07-07 23:32 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220707233249.EBEF7384A893@sourceware.org \
    --to=redi@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).