From 7e1b6610a21b451ca8aacf5b22c95f4139df43d6 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 28 Jun 2024 18:49:58 +0200 Subject: [PATCH] memory: avoid undefined behaviour from downcasting ptr implentation (#5) * sharedptr: dont downcast ptr implentation avoid runtime errors of wrong downcasts by adding a underlaying ptr data getter and only cast the data, downcasting the implentation type isnt inherited from eachother, while the intention was do upcast/downcast a derived class to a base class. found with UBSAN "runtime error: downcast of address which does not point to an object of type "CSharedPointer_::impl" note: object is of type "Hyprutils::Memory::CSharedPointer_::impl" also make dataNonNull check against != nullptr. * sharedptr: use reinterpret_cast instead of c style make it more type safe, C style casts tries every single one until one works, or not. compilers also produces better warnings/errors when using c++ casts in favour of C style ones. --- include/hyprutils/memory/SharedPtr.hpp | 13 +++++++++---- include/hyprutils/memory/WeakPtr.hpp | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/hyprutils/memory/SharedPtr.hpp b/include/hyprutils/memory/SharedPtr.hpp index 8cc8ee2..81ea705 100644 --- a/include/hyprutils/memory/SharedPtr.hpp +++ b/include/hyprutils/memory/SharedPtr.hpp @@ -20,7 +20,7 @@ namespace Hyprutils { namespace CSharedPointer_ { class impl_base { public: - virtual ~impl_base(){}; + virtual ~impl_base() {}; virtual void inc() noexcept = 0; virtual void dec() noexcept = 0; @@ -31,6 +31,7 @@ namespace Hyprutils { virtual void destroy() noexcept = 0; virtual bool destroying() noexcept = 0; virtual bool dataNonNull() noexcept = 0; + virtual void* getData() noexcept = 0; }; template @@ -107,6 +108,10 @@ namespace Hyprutils { } virtual bool dataNonNull() noexcept { + return _data != nullptr; + } + + virtual void* getData() noexcept { return _data; } @@ -213,11 +218,11 @@ namespace Hyprutils { } bool operator()(const CSharedPointer& lhs, const CSharedPointer& rhs) const { - return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_; + return reinterpret_cast(lhs.impl_) < reinterpret_cast(rhs.impl_); } bool operator<(const CSharedPointer& rhs) const { - return (uintptr_t)impl_ < (uintptr_t)rhs.impl_; + return reinterpret_cast(impl_) < reinterpret_cast(rhs.impl_); } T* operator->() const { @@ -234,7 +239,7 @@ namespace Hyprutils { } T* get() const { - return (T*)(impl_ ? static_cast*>(impl_)->_data : nullptr); + return impl_ ? static_cast(impl_->getData()) : nullptr; } unsigned int strongRef() const { diff --git a/include/hyprutils/memory/WeakPtr.hpp b/include/hyprutils/memory/WeakPtr.hpp index 8c62fa4..cd0d4bd 100644 --- a/include/hyprutils/memory/WeakPtr.hpp +++ b/include/hyprutils/memory/WeakPtr.hpp @@ -80,7 +80,7 @@ namespace Hyprutils { /* create a weak ptr from a shared ptr with assignment */ template validHierarchy&> operator=(const CSharedPointer& rhs) { - if ((uintptr_t)impl_ == (uintptr_t)rhs.impl_) + if (reinterpret_cast(impl_) == reinterpret_cast(rhs.impl_)) return *this; decrementWeak(); @@ -139,15 +139,15 @@ namespace Hyprutils { } bool operator()(const CWeakPointer& lhs, const CWeakPointer& rhs) const { - return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_; + return reinterpret_cast(lhs.impl_) < reinterpret_cast(rhs.impl_); } bool operator<(const CWeakPointer& rhs) const { - return (uintptr_t)impl_ < (uintptr_t)rhs.impl_; + return reinterpret_cast(impl_) < reinterpret_cast(rhs.impl_); } T* get() const { - return (T*)(impl_ ? static_cast*>(impl_)->_data : nullptr); + return impl_ ? static_cast(impl_->getData()) : nullptr; } T* operator->() const {