Fix Bug 30240 - std::string: append(first, last) error when aliasing. Add test cases for append/insert/assign/replace while we're at it, and fix a similar bug in insert.
llvm-svn: 280643
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 7e1a23001d68893ee10d68e8664021a00fa0bb2c
diff --git a/include/string b/include/string
index 53ddf5e..cfae0c8 100644
--- a/include/string
+++ b/include/string
@@ -1998,7 +1998,7 @@
>::type
basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
{
- basic_string __temp(__first, __last, __alloc());
+ const basic_string __temp(__first, __last, __alloc());
assign(__temp.data(), __temp.size());
return *this;
}
@@ -2151,11 +2151,17 @@
>::type
basic_string<_CharT, _Traits, _Allocator>::append(_InputIterator __first, _InputIterator __last)
{
- basic_string __temp (__first, __last, __alloc());
+ const basic_string __temp (__first, __last, __alloc());
append(__temp.data(), __temp.size());
return *this;
}
+template <typename _Tp>
+bool __ptr_in_range (const _Tp* __p, const _Tp* __first, const _Tp* __last)
+{
+ return __first <= __p && __p < __last;
+}
+
template <class _CharT, class _Traits, class _Allocator>
template<class _ForwardIterator>
typename enable_if
@@ -2171,13 +2177,21 @@
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
if (__n)
{
- if (__cap - __sz < __n)
- __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
- pointer __p = __get_pointer() + __sz;
- for (; __first != __last; ++__p, ++__first)
- traits_type::assign(*__p, *__first);
- traits_type::assign(*__p, value_type());
- __set_size(__sz + __n);
+ if ( __ptr_in_range(&*__first, data(), data() + size()))
+ {
+ const basic_string __temp (__first, __last, __alloc());
+ append(__temp.data(), __temp.size());
+ }
+ else
+ {
+ if (__cap - __sz < __n)
+ __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
+ pointer __p = __get_pointer() + __sz;
+ for (; __first != __last; ++__p, ++__first)
+ traits_type::assign(*__p, *__first);
+ traits_type::assign(*__p, value_type());
+ __set_size(__sz + __n);
+ }
}
return *this;
}
@@ -2299,7 +2313,7 @@
"string::insert(iterator, range) called with an iterator not"
" referring to this string");
#endif
- basic_string __temp(__first, __last, __alloc());
+ const basic_string __temp(__first, __last, __alloc());
return insert(__pos, __temp.data(), __temp.data() + __temp.size());
}
@@ -2319,11 +2333,17 @@
" referring to this string");
#endif
size_type __ip = static_cast<size_type>(__pos - begin());
- size_type __sz = size();
- size_type __cap = capacity();
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
if (__n)
{
+ if ( __ptr_in_range(&*__first, data(), data() + size()))
+ {
+ const basic_string __temp(__first, __last, __alloc());
+ return insert(__pos, __temp.data(), __temp.data() + __temp.size());
+ }
+
+ size_type __sz = size();
+ size_type __cap = capacity();
value_type* __p;
if (__cap - __sz >= __n)
{
@@ -2523,7 +2543,7 @@
basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,
_InputIterator __j1, _InputIterator __j2)
{
- basic_string __temp(__j1, __j2, __alloc());
+ const basic_string __temp(__j1, __j2, __alloc());
return this->replace(__i1, __i2, __temp);
}