summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarshall Clow <mclow.lists@gmail.com>2014-07-17 15:32:20 +0000
committerMarshall Clow <mclow.lists@gmail.com>2014-07-17 15:32:20 +0000
commit3dd88468404bf9117ade3dfc738cb728a6f958d3 (patch)
treedaf45fff893a31938ea402da3d27021df503e3ad
parent18cfe7d634935c08fc3647d61a1402b69500d6af (diff)
downloadbcm5719-llvm-3dd88468404bf9117ade3dfc738cb728a6f958d3.tar.gz
bcm5719-llvm-3dd88468404bf9117ade3dfc738cb728a6f958d3.zip
Fix bug #20335 - memory leak when move-constructing a string with unequal allocator. Thanks to Thomas Koeppe for the report
llvm-svn: 213269
-rw-r--r--libcxx/include/string30
-rw-r--r--libcxx/test/strings/basic.string/string.cons/move_alloc.pass.cpp10
2 files changed, 26 insertions, 14 deletions
diff --git a/libcxx/include/string b/libcxx/include/string
index d07ff289bb6..d6c148ac6da 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1031,16 +1031,16 @@ __str_rfind(const _CharT *__p, _SizeT __sz,
_CharT __c, _SizeT __pos) _NOEXCEPT
{
if (__sz < 1)
- return __npos;
- if (__pos < __sz)
- ++__pos;
- else
- __pos = __sz;
- for (const _CharT* __ps = __p + __pos; __ps != __p;)
- {
- if (_Traits::eq(*--__ps, __c))
- return static_cast<_SizeT>(__ps - __p);
- }
+ return __npos;
+ if (__pos < __sz)
+ ++__pos;
+ else
+ __pos = __sz;
+ for (const _CharT* __ps = __p + __pos; __ps != __p;)
+ {
+ if (_Traits::eq(*--__ps, __c))
+ return static_cast<_SizeT>(__ps - __p);
+ }
return __npos;
}
@@ -2136,11 +2136,13 @@ inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a)
: __r_(__a)
{
- if (__a == __str.__alloc() || !__str.__is_long())
- __r_.first().__r = __str.__r_.first().__r;
- else
+ if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
__init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size());
- __str.__zero();
+ else
+ {
+ __r_.first().__r = __str.__r_.first().__r;
+ __str.__zero();
+ }
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_c(this);
if (__is_long())
diff --git a/libcxx/test/strings/basic.string/string.cons/move_alloc.pass.cpp b/libcxx/test/strings/basic.string/string.cons/move_alloc.pass.cpp
index 4e8b038ee84..1f9631449ee 100644
--- a/libcxx/test/strings/basic.string/string.cons/move_alloc.pass.cpp
+++ b/libcxx/test/strings/basic.string/string.cons/move_alloc.pass.cpp
@@ -45,6 +45,16 @@ int main()
test(S("1"), A(5));
test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
}
+
+ int alloc_count = test_alloc_base::alloc_count;
+ {
+ typedef test_allocator<char> A;
+ typedef std::basic_string<char, std::char_traits<char>, A> S;
+ S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe" );
+ S s2 (std::move(s1), A(1));
+ }
+ assert ( test_alloc_base::alloc_count == alloc_count );
+
#if __cplusplus >= 201103L
{
typedef min_allocator<char> A;
OpenPOWER on IntegriCloud