-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Closed
Labels
bugzillaIssues migrated from bugzillaIssues migrated from bugzillaconfirmedVerified by a second partyVerified by a second partygood first issuehttps://github.com/llvm/llvm-project/contributehttps://github.com/llvm/llvm-project/contributelibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Description
Bugzilla Link | 41114 |
Version | trunk |
OS | All |
CC | @zygoloid |
Extended Description
cat >test.cc <<EOF
#include <memory>
#include <stdio.h>
struct A { int i = 0; virtual ~A() {} };
struct B : public virtual A { char d[100000]; };
int main() {
std::weak_ptr<B> p = std::shared_ptr<B>(new B);
puts("hello world");
std::weak_ptr<A> q = p;
}
EOF
clang++ -std=c++11 test.cc
./a.out
Segmentation fault
What's going on here is that the converting constructor weak_ptr(const weak_ptr&) is implemented as
weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_), // LINE XXX
__cntrl_(__r.__cntrl_)
{
if (__cntrl_)
__cntrl_->__add_weak();
}
When _Tp
is a virtual base of _Yp
, the conversion on line XXX generally needs to dereference __r.__ptr_
to compute the appropriate offset. This is fine if the weak_ptr stores a null pointer value, and it's fine if the weak_ptr is not-expired; but if the weak_ptr is expired (or empty) and stores a non-null pointer value, then we dereference into freed memory and segfault.
The solution adopted by both libstdc++ and MSVC is to implement this constructor as essentially
weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
_NOEXCEPT
: weak_ptr(__r.lock())
{}
Metadata
Metadata
Assignees
Labels
bugzillaIssues migrated from bugzillaIssues migrated from bugzillaconfirmedVerified by a second partyVerified by a second partygood first issuehttps://github.com/llvm/llvm-project/contributehttps://github.com/llvm/llvm-project/contributelibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.