From b6128b6fe02ae9707950b999dfe7ec40968ee530 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 10 Oct 2018 00:17:25 +0300 Subject: [PATCH] Fix undefined behaviour in base::weak_ptr. Regression was introduced in 1c79f85d00. Invalid casts lead to crashes in macOS notifications handling. Casts were T* -> has_weak_ptr* -> void* -> T* which was not working in case T had has_weak_ptr as not first base class. Now it uses just T* -> has_weak_ptr* -> T* casts. --- Telegram/SourceFiles/base/weak_ptr.h | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Telegram/SourceFiles/base/weak_ptr.h b/Telegram/SourceFiles/base/weak_ptr.h index ddab64a2e..76dd3de83 100644 --- a/Telegram/SourceFiles/base/weak_ptr.h +++ b/Telegram/SourceFiles/base/weak_ptr.h @@ -11,14 +11,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include namespace base { + +class has_weak_ptr; + namespace details { struct alive_tracker { - explicit alive_tracker(const void *value) : value(value) { + explicit alive_tracker(const has_weak_ptr *value) : value(value) { } std::atomic counter = 1; - std::atomic value; + std::atomic value; }; inline alive_tracker *check_and_increment(alive_tracker *tracker) noexcept { @@ -36,8 +39,6 @@ inline void decrement(alive_tracker *tracker) noexcept { } // namespace details -class has_weak_ptr; - template class weak_ptr; @@ -69,8 +70,7 @@ private: details::alive_tracker *incrementAliveTracker() const { auto current = _alive.load(); if (!current) { - auto alive = std::make_unique( - static_cast(this)); + auto alive = std::make_unique(this); if (_alive.compare_exchange_strong(current, alive.get())) { return alive.release(); } @@ -178,15 +178,11 @@ public: } T *get() const noexcept { + const auto strong = _alive ? _alive->value.load() : nullptr; if constexpr (std::is_const_v) { - return _alive - ? static_cast(_alive->value.load()) - : nullptr; + return static_cast(strong); } else { - return _alive - ? const_cast( - static_cast(_alive->value.load())) - : nullptr; + return const_cast(static_cast(strong)); } } explicit operator bool() const noexcept {