diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2009-06-23 12:36:43 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2009-06-23 12:36:43 +0000 |
commit | 7309083f99e306bd9f8512be3c7f4093cbbb13d0 (patch) | |
tree | e75e40c13a65e7f0449922ee1c3c4606a42e111a /libstdc++-v3 | |
parent | 2724e58f9632352aecea376a0fdbbae54c4a2895 (diff) | |
download | gcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.zip gcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.tar.gz gcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.tar.bz2 |
re PR libstdc++/40518 (data races when calling std::string::erase() on empty string)
2009-06-23 Paolo Carlini <paolo.carlini@oracle.com>
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
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/basic_string.h | 29 | ||||
-rw-r--r-- | 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 fc14048..a92920e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2009-06-23 Paolo Carlini <paolo.carlini@oracle.com> + + 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 <paolo.carlini@oracle.com> * 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 1e8300d..085aea4 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 ec771c6..d450a47 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -386,6 +386,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } template<typename _CharT, typename _Traits, typename _Alloc> + 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<typename _CharT, typename _Traits, typename _Alloc> basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: replace(size_type __pos, size_type __n1, const _CharT* __s, |