[libcxx] r280643 - 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.

Marshall Clow via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 4 18:54:30 PDT 2016


Author: marshall
Date: Sun Sep  4 20:54:30 2016
New Revision: 280643

URL: http://llvm.org/viewvc/llvm-project?rev=280643&view=rev
Log:
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.

Modified:
    libcxx/trunk/include/string
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Sun Sep  4 20:54:30 2016
@@ -1998,7 +1998,7 @@ typename enable_if
 >::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 @@ typename enable_if
 >::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 @@ basic_string<_CharT, _Traits, _Allocator
     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 @@ basic_string<_CharT, _Traits, _Allocator
         "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 @@ basic_string<_CharT, _Traits, _Allocator
         " 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 @@ typename enable_if
 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);
 }
 

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp Sun Sep  4 20:54:30 2016
@@ -178,4 +178,21 @@ int main()
     test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
 	}
 #endif
+
+	{ // test appending to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.append(s_short.begin(), s_short.end());
+	assert(s_short == "123/123/");
+	s_short.append(s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/");
+	s_short.append(s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.append(s_long.begin(), s_long.end());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
+
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp Sun Sep  4 20:54:30 2016
@@ -61,4 +61,20 @@ int main()
          S("1234567890123456789012345678901234567890"));
     }
 #endif
+
+	{ // test appending to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.append(s_short.c_str());
+	assert(s_short == "123/123/");
+	s_short.append(s_short.c_str());
+	assert(s_short == "123/123/123/123/");
+	s_short.append(s_short.c_str());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.append(s_long.c_str());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp Sun Sep  4 20:54:30 2016
@@ -70,4 +70,20 @@ int main()
          S("1234567890123456789012345678901234567890"));
     }
 #endif
+
+	{ // test appending to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.append(s_short.data(), s_short.size());
+	assert(s_short == "123/123/");
+	s_short.append(s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/");
+	s_short.append(s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.append(s_long.data(), s_long.size());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp Sun Sep  4 20:54:30 2016
@@ -179,4 +179,21 @@ int main()
     test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
 	}
 #endif
+
+	{ // test assigning to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.assign(s_short.begin(), s_short.end());
+	assert(s_short == "123/");
+	s_short.assign(s_short.begin() + 2, s_short.end());
+	assert(s_short == "3/");
+	
+	s_long.assign(s_long.begin(), s_long.end());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/");
+
+	s_long.assign(s_long.begin() + 30, s_long.end());
+	assert(s_long == "nsectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp Sun Sep  4 20:54:30 2016
@@ -61,4 +61,18 @@ int main()
          S("12345678901234567890"));
     }
 #endif
+
+	{ // test assignment to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.assign(s_short.c_str());
+	assert(s_short == "123/");
+	s_short.assign(s_short.c_str() + 2);
+	assert(s_short == "3/");
+	
+	s_long.assign(s_long.c_str() + 30);
+	assert(s_long == "nsectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp Sun Sep  4 20:54:30 2016
@@ -70,4 +70,20 @@ int main()
          S("12345678901234567890"));
     }
 #endif
+	{ // test assign to self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.assign(s_short.data(), s_short.size());
+	assert(s_short == "123/");
+	s_short.assign(s_short.data() + 2, s_short.size() - 2);
+	assert(s_short == "3/");
+	
+	s_long.assign(s_long.data(), s_long.size());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/");
+
+	s_long.assign(s_long.data() + 2, 8 );
+	assert(s_long == "rem ipsu");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp Sun Sep  4 20:54:30 2016
@@ -169,4 +169,21 @@ int main()
         assert(false);
     }
 #endif
+
+	{ // test inserting into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/");
+	s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/");
+	s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.insert(s_long.begin(), s_long.begin(), s_long.end());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
+
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp Sun Sep  4 20:54:30 2016
@@ -210,4 +210,20 @@ int main()
     test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", S("can't happen"));
     }
 #endif
+
+	{ // test inserting into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.insert(0, s_short.c_str());
+	assert(s_short == "123/123/");
+	s_short.insert(0, s_short.c_str());
+	assert(s_short == "123/123/123/123/");
+	s_short.insert(0, s_short.c_str());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.insert(0, s_long.c_str());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp Sun Sep  4 20:54:30 2016
@@ -691,4 +691,20 @@ int main()
     test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"));
     }
 #endif
+
+	{ // test inserting into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.insert(0, s_short.data(), s_short.size());
+	assert(s_short == "123/123/");
+	s_short.insert(0, s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/");
+	s_short.insert(0, s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.insert(0, s_long.data(), s_long.size());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp Sun Sep  4 20:54:30 2016
@@ -1007,4 +1007,20 @@ int main()
     test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 6, TIter::TAComparison), TIter());
 	}
 #endif
+
+	{ // test replacing into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.replace(s_long.begin(), s_long.begin(), s_long.begin(), s_long.end());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp Sun Sep  4 20:54:30 2016
@@ -282,4 +282,20 @@ int main()
     test2<S>();
     }
 #endif
+
+	{ // test replacing into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str());
+	assert(s_short == "123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str());
+	assert(s_short == "123/123/123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.replace(s_long.begin(), s_long.begin(), s_long.c_str());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp Sun Sep  4 20:54:30 2016
@@ -972,4 +972,20 @@ int main()
     test8<S>();
     }
 #endif
+
+	{ // test replacing into self
+    typedef std::string S;
+	S s_short = "123/";
+	S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
+	
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size());
+	assert(s_short == "123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/");
+	s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size());
+	assert(s_short == "123/123/123/123/123/123/123/123/");
+	
+	s_long.replace(s_long.begin(), s_long.begin(), s_long.data(), s_long.size());
+	assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
+	}
 }




More information about the cfe-commits mailing list