diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 312f39c41ba..65890ea4b6b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2018-08-14 Jeremy Sawicki + + * include/ext/rope (_Rope_iterator_base(const _Rope_iterator_base&)) + (_Rope_const_iterator::operator=(const _Rope_const_iterator&)) + (_Rope_iterator::operator=(const _Rope_iterator&)): Ensure + copied/assigned rope iterators don't retain pointers to the iterator + they were copied/assigned from. + * testsuite/ext/rope/7.cc: New. + 2018-08-13 Jonathan Wakely PR libstdc++/45093 diff --git a/libstdc++-v3/include/ext/rope b/libstdc++-v3/include/ext/rope index a53d2e07a32..a172989a2f9 100644 --- a/libstdc++-v3/include/ext/rope +++ b/libstdc++-v3/include/ext/rope @@ -1119,7 +1119,7 @@ protected: _Rope_iterator_base(const _Rope_iterator_base& __x) { - if (0 != __x._M_buf_ptr) + if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf) *this = __x; else { @@ -1166,7 +1166,7 @@ protected: _Rope_const_iterator& operator=(const _Rope_const_iterator& __x) { - if (0 != __x._M_buf_ptr) + if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf) *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x; else { @@ -1345,7 +1345,7 @@ protected: _RopeRep* __old = this->_M_root; _RopeRep::_S_ref(__x._M_root); - if (0 != __x._M_buf_ptr) + if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf) { _M_root_rope = __x._M_root_rope; *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x; diff --git a/libstdc++-v3/testsuite/ext/rope/7.cc b/libstdc++-v3/testsuite/ext/rope/7.cc new file mode 100644 index 00000000000..a9274943b6b --- /dev/null +++ b/libstdc++-v3/testsuite/ext/rope/7.cc @@ -0,0 +1,95 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// rope (SGI extension) + +// { dg-do run } + +#include +#include + +void +test01() +{ + using __gnu_cxx::crope; + + char str_a[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + char str_b[] = + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + + // Create ropes with leaf nodes longer than __lazy_threshold = 128 + // so substring nodes will be created by the next step + crope leaf_rope_a(str_a); + crope leaf_rope_b(str_b); + + // Create ropes with substring nodes referencing the leaf nodes + // of the prior ropes + crope substring_rope_a(leaf_rope_a.begin() + 1, + leaf_rope_a.begin() + 199); + crope substring_rope_b(leaf_rope_b.begin() + 1, + leaf_rope_b.begin() + 199); + + // Create iterators to substring_rope_a + crope::const_iterator cit_orig = substring_rope_a.begin(); + crope::iterator mit_orig = substring_rope_a.mutable_begin(); + + // Dereference the iterators so they cache a portion of the substring + // node in their internal buffers + *cit_orig; + *mit_orig; + + // Copy the original iterators, via both copy constructors and + // assignment operators. Prior to the bug fix, these iterators + // retained pointers to the internal buffers of the original + // iterators. + crope::const_iterator cit_copy(cit_orig); + crope::iterator mit_copy(mit_orig); + crope::const_iterator cit_assign; cit_assign = cit_orig; + crope::iterator mit_assign; mit_assign = mit_orig; + + // Modify the original iterators to refer to substring_rope_b + cit_orig = substring_rope_b.begin(); + mit_orig = substring_rope_b.mutable_begin(); + + // Dereference the original iterators so they fill their internal + // buffers with part of substring_rope_b + *cit_orig; + *mit_orig; + + // Verify that the copied iterators return data from + // substring_rope_a, not substring_rope_b + VERIFY(*cit_copy == 'a'); + VERIFY(*mit_copy == 'a'); + VERIFY(*cit_assign == 'a'); + VERIFY(*mit_assign == 'a'); +} + +int +main() +{ + test01(); + return 0; +}