[libcxx-commits] [libcxx] [libc++] Fix a segfault in weak_ptr(const weak_ptr<Y>&) (PR #67956)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 2 00:36:57 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
<details>
<summary>Changes</summary>
Fixes https://github.com/llvm/llvm-project/issues/40459
---
Full diff: https://github.com/llvm/llvm-project/pull/67956.diff
2 Files Affected:
- (modified) libcxx/include/__memory/shared_ptr.h (+9-8)
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/pr40459.pass.cpp (+61)
``````````diff
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 6be2f22184590ae..33a1b95a31ddbd5 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -1727,11 +1727,11 @@ template<class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> >
inline
weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r)
_NOEXCEPT
- : __ptr_(__r.__ptr_),
- __cntrl_(__r.__cntrl_)
+ : __ptr_(nullptr),
+ __cntrl_(nullptr)
{
- if (__cntrl_)
- __cntrl_->__add_weak();
+ shared_ptr<_Yp> __s = __r.lock();
+ *this = weak_ptr<_Tp>(__s);
}
template<class _Tp>
@@ -1749,11 +1749,12 @@ template<class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> >
inline
weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r)
_NOEXCEPT
- : __ptr_(__r.__ptr_),
- __cntrl_(__r.__cntrl_)
+ : __ptr_(nullptr),
+ __cntrl_(nullptr)
{
- __r.__ptr_ = nullptr;
- __r.__cntrl_ = nullptr;
+ shared_ptr<_Yp> __s = __r.lock();
+ *this = weak_ptr<_Tp>(__s);
+ __r.reset();
}
template<class _Tp>
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/pr40459.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/pr40459.pass.cpp
new file mode 100644
index 000000000000000..25141ad2de6c992
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/pr40459.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// weak_ptr
+
+// template<class Y> weak_ptr(const weak_ptr<Y>& r);
+// template<class Y> weak_ptr(weak_ptr<Y>&& r);
+//
+// Regression test for https://github.com/llvm/llvm-project/issues/40459
+// Verify that these constructors never attempt a derived-to-virtual-base
+// conversion on a dangling weak_ptr.
+
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <utility>
+
+#include "test_macros.h"
+
+struct A {
+ int i;
+ virtual ~A() {}
+};
+struct B : public virtual A {
+ int j;
+};
+struct Deleter {
+ void operator()(void*) const {
+ // do nothing
+ }
+};
+
+int main(int, char**) {
+#if TEST_STD_VER >= 11
+ alignas(B) char buffer[sizeof(B)];
+#else
+ std::aligned_storage<sizeof(B), std::alignment_of<B>::value>::type buffer;
+#endif
+ B *pb = ::new ((void*)&buffer) B();
+ std::shared_ptr<B> sp = std::shared_ptr<B>(pb, Deleter());
+ std::weak_ptr<B> wp = sp;
+ sp = nullptr;
+ assert(wp.expired());
+
+ // Overwrite the B object with junk.
+ std::memset(&buffer, '*', sizeof(buffer));
+
+ std::weak_ptr<A> wq = wp;
+ assert(wq.expired());
+ std::weak_ptr<A> wr = std::move(wp);
+ assert(wr.expired());
+
+ return 0;
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/67956
More information about the libcxx-commits
mailing list