mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-19 00:55:13 +08:00
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.
This commit is contained in:
parent
3788c4ed2c
commit
ef5d671cd8
@ -2488,6 +2488,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.
|
||||
@ -2511,7 +2520,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2534,7 +2544,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,
|
||||
|
@ -461,9 +461,9 @@ 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,
|
||||
__regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
|
||||
const basic_regex<_Ch_type, _Rx_traits>& __e,
|
||||
const _Ch_type* __fmt,
|
||||
const _Ch_type* __fmt, size_t __len,
|
||||
regex_constants::match_flag_type __flags)
|
||||
{
|
||||
typedef regex_iterator<_Bi_iter, _Ch_type, _Rx_traits> _IterT;
|
||||
@ -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))
|
||||
|
@ -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) );
|
||||
}
|
Loading…
Reference in New Issue
Block a user