[libcxx-commits] [libcxx] b861457 - [libc++] Fix a segfault in weak_ptr(const weak_ptr<Y>&) (#67956)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 2 14:52:38 PDT 2023
Author: Amirreza Ashouri
Date: 2023-10-02T17:52:34-04:00
New Revision: b861457c904c2f8d8f8a298fa3ddd2b309271692
URL: https://github.com/llvm/llvm-project/commit/b861457c904c2f8d8f8a298fa3ddd2b309271692
DIFF: https://github.com/llvm/llvm-project/commit/b861457c904c2f8d8f8a298fa3ddd2b309271692.diff
LOG: [libc++] Fix a segfault in weak_ptr(const weak_ptr<Y>&) (#67956)
Fixes https://github.com/llvm/llvm-project/issues/40459
Added:
libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/pr40459.pass.cpp
Modified:
libcxx/include/__memory/shared_ptr.h
Removed:
################################################################################
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..e94104fe8aa8ca5
--- /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;
+}
More information about the libcxx-commits
mailing list