[libcxx] r290721 - Fix PR31489 - std::function self-swap segfaults
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 29 12:03:55 PST 2016
Author: ericwf
Date: Thu Dec 29 14:03:55 2016
New Revision: 290721
URL: http://llvm.org/viewvc/llvm-project?rev=290721&view=rev
Log:
Fix PR31489 - std::function self-swap segfaults
Modified:
libcxx/trunk/include/__functional_03
libcxx/trunk/include/functional
libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
Modified: libcxx/trunk/include/__functional_03
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_03?rev=290721&r1=290720&r2=290721&view=diff
==============================================================================
--- libcxx/trunk/include/__functional_03 (original)
+++ libcxx/trunk/include/__functional_03 Thu Dec 29 14:03:55 2016
@@ -642,6 +642,8 @@ template<class _Rp>
void
function<_Rp()>::swap(function& __f)
{
+ if (_VSTD::addressof(__f) == this)
+ return;
if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
@@ -916,6 +918,8 @@ template<class _Rp, class _A0>
void
function<_Rp(_A0)>::swap(function& __f)
{
+ if (_VSTD::addressof(__f) == this)
+ return;
if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
@@ -1190,6 +1194,8 @@ template<class _Rp, class _A0, class _A1
void
function<_Rp(_A0, _A1)>::swap(function& __f)
{
+ if (_VSTD::addressof(__f) == this)
+ return;
if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
@@ -1464,6 +1470,8 @@ template<class _Rp, class _A0, class _A1
void
function<_Rp(_A0, _A1, _A2)>::swap(function& __f)
{
+ if (_VSTD::addressof(__f) == this)
+ return;
if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=290721&r1=290720&r2=290721&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Thu Dec 29 14:03:55 2016
@@ -1870,6 +1870,8 @@ template<class _Rp, class ..._ArgTypes>
void
function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT
{
+ if (_VSTD::addressof(__f) == this)
+ return;
if ((void *)__f_ == &__buf_ && (void *)__f.__f_ == &__f.__buf_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
Modified: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp?rev=290721&r1=290720&r2=290721&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp Thu Dec 29 14:03:55 2016
@@ -19,92 +19,120 @@
#include "test_macros.h"
#include "count_new.hpp"
-class A
-{
- int data_[10];
+class A {
+ int data_[10];
+
public:
- static int count;
+ static int count;
- A()
- {
- ++count;
- for (int i = 0; i < 10; ++i)
- data_[i] = i;
- }
-
- A(const A&) {++count;}
-
- ~A() {--count;}
-
- int operator()(int i) const
- {
- for (int j = 0; j < 10; ++j)
- i += data_[j];
- return i;
- }
+ A() {
+ ++count;
+ for (int i = 0; i < 10; ++i)
+ data_[i] = i;
+ }
+
+ A(const A &) { ++count; }
+
+ ~A() { --count; }
+
+ int operator()(int i) const {
+ for (int j = 0; j < 10; ++j)
+ i += data_[j];
+ return i;
+ }
};
int A::count = 0;
-int g(int) {return 0;}
-
-int main()
-{
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+int g0() { return 0; }
+int g(int) { return 0; }
+int g2(int, int) { return 2; }
+int g3(int, int, int) { return 3; }
+
+int main() {
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f = A();
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f.target<A>());
- assert(f.target<int(*)(int)>() == 0);
+ assert(f.target<int (*)(int)>() == 0);
std::function<int(int)> f2;
f2 = f;
assert(A::count == 2);
assert(globalMemCounter.checkOutstandingNewEq(2));
assert(f2.target<A>());
- assert(f2.target<int(*)(int)>() == 0);
- }
- assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ assert(f2.target<int (*)(int)>() == 0);
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f = g;
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(f.target<int(*)(int)>());
+ assert(f.target<int (*)(int)>());
assert(f.target<A>() == 0);
std::function<int(int)> f2;
f2 = f;
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(f2.target<int(*)(int)>());
+ assert(f2.target<int (*)(int)>());
assert(f2.target<A>() == 0);
- }
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f;
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(f.target<int(*)(int)>() == 0);
+ assert(f.target<int (*)(int)>() == 0);
assert(f.target<A>() == 0);
std::function<int(int)> f2;
f2 = f;
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(f2.target<int(*)(int)>() == 0);
+ assert(f2.target<int (*)(int)>() == 0);
assert(f2.target<A>() == 0);
- }
+ }
+ {
+ typedef std::function<int()> Func;
+ Func f = g0;
+ Func& fr = (f = f);
+ assert(&fr == &f);
+ assert(*f.target<int(*)()>() == g0);
+ }
+ {
+ typedef std::function<int(int)> Func;
+ Func f = g;
+ Func& fr = (f = f);
+ assert(&fr == &f);
+ assert(*f.target<int(*)(int)>() == g);
+ }
+ {
+ typedef std::function<int(int, int)> Func;
+ Func f = g2;
+ Func& fr = (f = f);
+ assert(&fr == &f);
+ assert(*f.target<int(*)(int, int)>() == g2);
+ }
+ {
+ typedef std::function<int(int, int, int)> Func;
+ Func f = g3;
+ Func& fr = (f = f);
+ assert(&fr == &f);
+ assert(*f.target<int(*)(int, int, int)>() == g3);
+ }
#if TEST_STD_VER >= 11
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f = A();
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f.target<A>());
- assert(f.target<int(*)(int)>() == 0);
+ assert(f.target<int (*)(int)>() == 0);
std::function<int(int)> f2;
f2 = std::move(f);
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f2.target<A>());
- assert(f2.target<int(*)(int)>() == 0);
+ assert(f2.target<int (*)(int)>() == 0);
assert(f.target<A>() == 0);
- assert(f.target<int(*)(int)>() == 0);
- }
+ assert(f.target<int (*)(int)>() == 0);
+ }
#endif
}
Modified: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp?rev=290721&r1=290720&r2=290721&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp Thu Dec 29 14:03:55 2016
@@ -18,46 +18,49 @@
#include "count_new.hpp"
-class A
-{
- int data_[10];
-public:
- static int count;
-
- explicit A(int j)
- {
- ++count;
- data_[0] = j;
- }
-
- A(const A& a)
- {
- ++count;
- for (int i = 0; i < 10; ++i)
- data_[i] = a.data_[i];
- }
+class A {
+ int data_[10];
- ~A() {--count;}
+public:
+ static int count;
- int operator()(int i) const
- {
- for (int j = 0; j < 10; ++j)
- i += data_[j];
- return i;
- }
+ explicit A(int j) {
+ ++count;
+ data_[0] = j;
+ }
+
+ A(const A &a) {
+ ++count;
+ for (int i = 0; i < 10; ++i)
+ data_[i] = a.data_[i];
+ }
+
+ ~A() { --count; }
+
+ int operator()(int i) const {
+ for (int j = 0; j < 10; ++j)
+ i += data_[j];
+ return i;
+ }
+
+ int operator()() const { return -1; }
+ int operator()(int, int) const { return -2; }
+ int operator()(int, int, int) const { return -3; }
- int id() const {return data_[0];}
+ int id() const { return data_[0]; }
};
int A::count = 0;
-int g(int) {return 0;}
-int h(int) {return 1;}
-
-int main()
-{
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+int g0() { return 0; }
+int g(int) { return 0; }
+int h(int) { return 1; }
+int g2(int, int) { return 2; }
+int g3(int, int, int) { return 3; }
+
+int main() {
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f1 = A(1);
std::function<int(int)> f2 = A(2);
assert(A::count == 2);
@@ -69,52 +72,122 @@ int main()
assert(globalMemCounter.checkOutstandingNewEq(2));
assert(f1.target<A>()->id() == 2);
assert(f2.target<A>()->id() == 1);
- }
- assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f1 = A(1);
std::function<int(int)> f2 = g;
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f1.target<A>()->id() == 1);
- assert(*f2.target<int(*)(int)>() == g);
+ assert(*f2.target<int (*)(int)>() == g);
f1.swap(f2);
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
- assert(*f1.target<int(*)(int)>() == g);
+ assert(*f1.target<int (*)(int)>() == g);
assert(f2.target<A>()->id() == 1);
- }
- assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f1 = g;
std::function<int(int)> f2 = A(1);
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
- assert(*f1.target<int(*)(int)>() == g);
+ assert(*f1.target<int (*)(int)>() == g);
assert(f2.target<A>()->id() == 1);
f1.swap(f2);
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f1.target<A>()->id() == 1);
- assert(*f2.target<int(*)(int)>() == g);
- }
- assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
- {
+ assert(*f2.target<int (*)(int)>() == g);
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
std::function<int(int)> f1 = g;
std::function<int(int)> f2 = h;
assert(A::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(*f1.target<int(*)(int)>() == g);
- assert(*f2.target<int(*)(int)>() == h);
+ assert(*f1.target<int (*)(int)>() == g);
+ assert(*f2.target<int (*)(int)>() == h);
f1.swap(f2);
assert(A::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(*f1.target<int(*)(int)>() == h);
- assert(*f2.target<int(*)(int)>() == g);
+ assert(*f1.target<int (*)(int)>() == h);
+ assert(*f2.target<int (*)(int)>() == g);
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
+ std::function<int(int)> f1 = A(1);
+ assert(A::count == 1);
+ {
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
}
- assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(A::count == 1);
+ assert(f1.target<A>()->id() == 1);
+ }
+ assert(A::count == 0);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
+ std::function<int()> f1 = g0;
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(*f1.target<int (*)()>() == g0);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
+ std::function<int(int, int)> f1 = g2;
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(*f1.target<int (*)(int, int)>() == g2);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
+ std::function<int(int, int, int)> f1 = g3;
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(*f1.target<int (*)(int, int, int)>() == g3);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ {
+ std::function<int()> f1 = A(1);
+ assert(A::count == 1);
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(A::count == 1);
+ assert(f1.target<A>()->id() == 1);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(A::count == 0);
+ {
+ std::function<int(int, int)> f1 = A(2);
+ assert(A::count == 1);
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(A::count == 1);
+ assert(f1.target<A>()->id() == 2);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(A::count == 0);
+ {
+ std::function<int(int, int, int)> f1 = A(3);
+ assert(A::count == 1);
+ DisableAllocationGuard guard;
+ ((void)guard);
+ f1.swap(f1);
+ assert(A::count == 1);
+ assert(f1.target<A>()->id() == 3);
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(A::count == 0);
}
More information about the cfe-commits
mailing list