From 7309083f99e306bd9f8512be3c7f4093cbbb13d0 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 23 Jun 2009 12:36:43 +0000 Subject: [PATCH] re PR libstdc++/40518 (data races when calling std::string::erase() on empty string) 2009-06-23 Paolo Carlini PR libstdc++/40518 * include/bits/basic_string.h (basic_string<>::_Rep:: _M_set_length_and_sharable): Do not write the empty rep. (basic_string<>::erase(iterator, iterator)): Likewise, move out of line... * include/bits/basic_string.tcc: ... here. From-SVN: r148850 --- libstdc++-v3/ChangeLog | 9 +++++++ libstdc++-v3/include/bits/basic_string.h | 29 ++++++++++------------ libstdc++-v3/include/bits/basic_string.tcc | 23 +++++++++++++++++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fc140487c81..a92920efdb8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2009-06-23 Paolo Carlini + + PR libstdc++/40518 + * include/bits/basic_string.h (basic_string<>::_Rep:: + _M_set_length_and_sharable): Do not write the empty rep. + (basic_string<>::erase(iterator, iterator)): Likewise, + move out of line... + * include/bits/basic_string.tcc: ... here. + 2009-06-22 Paolo Carlini * testsuite/util/testsuite_common_types.h (bitwise_operators, diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 1e8300dabfa..085aea463b6 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -197,12 +197,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std) void _M_set_length_and_sharable(size_type __n) - { - this->_M_set_sharable(); // One reference. - this->_M_length = __n; - traits_type::assign(this->_M_refdata()[__n], _S_terminal); - // grrr. (per 21.3.4) - // You cannot leave those LWG people alone for a second. + { +#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING + if (__builtin_expect(this != &_S_empty_rep(), false)) +#endif + { + this->_M_set_sharable(); // One reference. + this->_M_length = __n; + traits_type::assign(this->_M_refdata()[__n], _S_terminal); + // grrr. (per 21.3.4) + // You cannot leave those LWG people alone for a second. + } } _CharT* @@ -1226,16 +1231,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * The value of the string doesn't change if an error is thrown. */ iterator - erase(iterator __first, iterator __last) - { - _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last - && __last <= _M_iend()); - const size_type __pos = __first - _M_ibegin(); - _M_mutate(__pos, __last - __first, size_type(0)); - _M_rep()->_M_set_leaked(); - return iterator(_M_data() + __pos); - } - + erase(iterator __first, iterator __last); + /** * @brief Replace characters with value from another string. * @param pos Index of first character to replace. diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index ec771c66859..d450a4717de 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -385,6 +385,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } } + template + typename basic_string<_CharT, _Traits, _Alloc>::iterator + basic_string<_CharT, _Traits, _Alloc>:: + erase(iterator __first, iterator __last) + { + _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last + && __last <= _M_iend()); + + // NB: This isn't just an optimization (bail out early when + // there is nothing to do, really), it's also a correctness + // issue vs MT, see libstdc++/40518. + const size_type __size = __last - __first; + if (__size) + { + const size_type __pos = __first - _M_ibegin(); + _M_mutate(__pos, __size, size_type(0)); + _M_rep()->_M_set_leaked(); + return iterator(_M_data() + __pos); + } + else + return __first; + } + template basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: -- 2.30.2