From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 493533858284; Fri, 23 Jun 2023 16:12:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 493533858284 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1687536752; bh=ynOWsgwswNT3NQ8JmDDEPWKQyHxzM8Mtb6+ECNtXFDY=; h=From:To:Subject:Date:From; b=X10f9Ru95I0nAGBZRkwsLOHEw/+R+L3CfejIfDcnIyW3iu9mGmLlFF51vgEEX6swM PkVZIF7gFwXb4/PrBBDlWwc4M2mLk+YxQW4f9aECJiIKxjLKcF7GVcl0KzrZCD/mEs QlqTuDtx6UMiKpeRRKiYCjD7lGRdP+dLpWNlmke4= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r10-11462] libstdc++: Fix std::regex_replace for strings with embedded null [PR103664] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-10 X-Git-Oldrev: d877bf3bdf46b5c996505fc247d170e79fbfa4bf X-Git-Newrev: 364cb498c472790e14561f7672dc5ab4a9222287 Message-Id: <20230623161232.493533858284@sourceware.org> Date: Fri, 23 Jun 2023 16:12:32 +0000 (GMT) List-Id: https://gcc.gnu.org/g:364cb498c472790e14561f7672dc5ab4a9222287 commit r10-11462-g364cb498c472790e14561f7672dc5ab4a9222287 Author: Jonathan Wakely 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 3fded333d47..c7630869548 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -2457,6 +2457,15 @@ _GLIBCXX_END_NAMESPACE_CXX11 = regex_constants::match_default) = delete; // std [28.11.4] Function template regex_replace + + template + _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. @@ -2480,7 +2489,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); } /** @@ -2503,7 +2513,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 0ca4f7a7c43..5ff01d115f0 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -461,10 +461,10 @@ namespace __detail template _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 +#include + +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) ); +}