Skip to content

Commit 117d6fc

Browse files
committed
memory: Add dynamic_cast to SP/ASP
1 parent 0168583 commit 117d6fc

File tree

4 files changed

+189
-24
lines changed

4 files changed

+189
-24
lines changed

include/hyprutils/memory/Atomic.hpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ namespace Hyprutils::Memory {
5454
using validHierarchy = std::enable_if_t<std::is_assignable_v<CAtomicSharedPointer<T>&, X>, CAtomicSharedPointer&>;
5555

5656
public:
57-
explicit CAtomicSharedPointer(T* object) noexcept : m_ptr(new Atomic_::impl(sc<void*>(object), _delete)) {
57+
explicit CAtomicSharedPointer(T* object) noexcept : m_ptr(new Atomic_::impl(sc<void*>(object), _delete), sc<void*>(object)) {
5858
;
5959
}
6060

61-
CAtomicSharedPointer(Impl_::impl_base* impl) noexcept : m_ptr(impl) {
61+
CAtomicSharedPointer(Impl_::impl_base* impl, void* data) noexcept : m_ptr(impl, data) {
6262
;
6363
}
6464

@@ -219,13 +219,17 @@ namespace Hyprutils::Memory {
219219
return m_ptr.impl_ ? m_ptr.impl_->ref() : 0;
220220
}
221221

222+
Atomic_::impl* impl() const {
223+
return sc<Atomic_::impl*>(m_ptr.impl_);
224+
}
225+
222226
private:
223227
static void _delete(void* p) {
224228
std::default_delete<T>{}(sc<T*>(p));
225229
}
226230

227231
std::lock_guard<std::recursive_mutex> implLockGuard() const {
228-
return sc<Atomic_::impl*>(m_ptr.impl_)->lockGuard();
232+
return impl()->lockGuard();
229233
}
230234

231235
CSharedPointer<T> m_ptr;
@@ -391,12 +395,16 @@ namespace Hyprutils::Memory {
391395
if (!m_ptr.impl_->dataNonNull() || m_ptr.impl_->destroying() || !m_ptr.impl_->lockable())
392396
return {};
393397

394-
return CAtomicSharedPointer<T>(m_ptr.impl_);
398+
return CAtomicSharedPointer<T>(m_ptr.impl_, m_ptr.m_data);
399+
}
400+
401+
Atomic_::impl* impl() const {
402+
return sc<Atomic_::impl*>(m_ptr.impl_);
395403
}
396404

397405
private:
398406
std::lock_guard<std::recursive_mutex> implLockGuard() const {
399-
return sc<Atomic_::impl*>(m_ptr.impl_)->lockGuard();
407+
return impl()->lockGuard();
400408
}
401409

402410
CWeakPointer<T> m_ptr;
@@ -411,4 +419,19 @@ namespace Hyprutils::Memory {
411419
[[nodiscard]] inline CAtomicSharedPointer<U> makeAtomicShared(Args&&... args) {
412420
return CAtomicSharedPointer<U>(new U(std::forward<Args>(args)...));
413421
}
422+
423+
template <typename T, typename U>
424+
CAtomicSharedPointer<T> reinterpretPointerCast(const CAtomicSharedPointer<U>& ref) {
425+
return CAtomicSharedPointer<T>(ref.impl(), ref.m_data);
426+
}
427+
428+
template <typename T, typename U>
429+
CAtomicSharedPointer<T> dynamicPointerCast(const CAtomicSharedPointer<U>& ref) {
430+
if (!ref)
431+
return nullptr;
432+
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl()->getData()));
433+
if (!newPtr)
434+
return nullptr;
435+
return CAtomicSharedPointer<T>(ref.impl(), newPtr);
436+
}
414437
}

include/hyprutils/memory/SharedPtr.hpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,33 @@ namespace Hyprutils {
2828

2929
/* creates a new shared pointer managing a resource
3030
avoid calling. Could duplicate ownership. Prefer makeShared */
31-
explicit CSharedPointer(T* object) noexcept : impl_(new Impl_::impl_base(sc<void*>(object), _delete)) {
31+
explicit CSharedPointer(T* object) noexcept : impl_(new Impl_::impl_base(sc<void*>(object), _delete)), m_data(sc<void*>(object)) {
3232
increment();
3333
}
3434

3535
/* creates a shared pointer from a reference */
3636
template <typename U, typename = isConstructible<U>>
37-
CSharedPointer(const CSharedPointer<U>& ref) noexcept : impl_(ref.impl_) {
37+
CSharedPointer(const CSharedPointer<U>& ref) noexcept : impl_(ref.impl_), m_data(ref.m_data) {
3838
increment();
3939
}
4040

41-
CSharedPointer(const CSharedPointer& ref) noexcept : impl_(ref.impl_) {
41+
CSharedPointer(const CSharedPointer& ref) noexcept : impl_(ref.impl_), m_data(ref.m_data) {
4242
increment();
4343
}
4444

4545
template <typename U, typename = isConstructible<U>>
4646
CSharedPointer(CSharedPointer<U>&& ref) noexcept {
4747
std::swap(impl_, ref.impl_);
48+
std::swap(m_data, ref.m_data);
4849
}
4950

5051
CSharedPointer(CSharedPointer&& ref) noexcept {
5152
std::swap(impl_, ref.impl_);
53+
std::swap(m_data, ref.m_data);
5254
}
5355

5456
/* allows weakPointer to create from an impl */
55-
CSharedPointer(Impl_::impl_base* implementation) noexcept : impl_(implementation) {
57+
CSharedPointer(Impl_::impl_base* implementation, void* data) noexcept : impl_(implementation), m_data(data) {
5658
increment();
5759
}
5860

@@ -74,7 +76,8 @@ namespace Hyprutils {
7476
return *this;
7577

7678
decrement();
77-
impl_ = rhs.impl_;
79+
impl_ = rhs.impl_;
80+
m_data = rhs.m_data;
7881
increment();
7982
return *this;
8083
}
@@ -84,26 +87,31 @@ namespace Hyprutils {
8487
return *this;
8588

8689
decrement();
87-
impl_ = rhs.impl_;
90+
impl_ = rhs.impl_;
91+
m_data = rhs.m_data;
8892
increment();
8993
return *this;
9094
}
9195

9296
template <typename U>
9397
validHierarchy<const CSharedPointer<U>&> operator=(CSharedPointer<U>&& rhs) {
9498
std::swap(impl_, rhs.impl_);
99+
std::swap(m_data, rhs.m_data);
95100
return *this;
96101
}
97102

98103
CSharedPointer& operator=(CSharedPointer&& rhs) noexcept {
99104
std::swap(impl_, rhs.impl_);
105+
std::swap(m_data, rhs.m_data);
100106
return *this;
101107
}
102108

103109
operator bool() const {
104110
return impl_ && impl_->dataNonNull();
105111
}
106112

113+
// this compares that the pointed-to object is the same, but in multiple inheritance,
114+
// different typed pointers can be equal if the object is the same
107115
bool operator==(const CSharedPointer& rhs) const {
108116
return impl_ == rhs.impl_;
109117
}
@@ -126,11 +134,12 @@ namespace Hyprutils {
126134

127135
void reset() {
128136
decrement();
129-
impl_ = nullptr;
137+
impl_ = nullptr;
138+
m_data = nullptr;
130139
}
131140

132141
T* get() const {
133-
return impl_ ? sc<T*>(impl_->getData()) : nullptr;
142+
return impl_ && impl_->dataNonNull() ? sc<T*>(m_data) : nullptr;
134143
}
135144

136145
unsigned int strongRef() const {
@@ -139,6 +148,9 @@ namespace Hyprutils {
139148

140149
Impl_::impl_base* impl_ = nullptr;
141150

151+
// Never use directly: raw data ptr, could be UAF
152+
void* m_data = nullptr;
153+
142154
private:
143155
static void _delete(void* p) {
144156
std::default_delete<T>{}(sc<T*>(p));
@@ -188,7 +200,17 @@ namespace Hyprutils {
188200

189201
template <typename T, typename U>
190202
CSharedPointer<T> reinterpretPointerCast(const CSharedPointer<U>& ref) {
191-
return CSharedPointer<T>(ref.impl_);
203+
return CSharedPointer<T>(ref.impl_, ref.m_data);
204+
}
205+
206+
template <typename T, typename U>
207+
CSharedPointer<T> dynamicPointerCast(const CSharedPointer<U>& ref) {
208+
if (!ref)
209+
return nullptr;
210+
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl_->getData()));
211+
if (!newPtr)
212+
return nullptr;
213+
return CSharedPointer<T>(ref.impl_, newPtr);
192214
}
193215
}
194216
}

include/hyprutils/memory/WeakPtr.hpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ namespace Hyprutils {
2626
if (!ref.impl_)
2727
return;
2828

29-
impl_ = ref.impl_;
29+
impl_ = ref.impl_;
30+
m_data = ref.m_data;
3031
incrementWeak();
3132
}
3233

@@ -36,7 +37,8 @@ namespace Hyprutils {
3637
if (!ref.impl_)
3738
return;
3839

39-
impl_ = ref.impl_;
40+
impl_ = ref.impl_;
41+
m_data = ref.impl_->getData();
4042
incrementWeak();
4143
}
4244

@@ -46,25 +48,29 @@ namespace Hyprutils {
4648
if (!ref.impl_)
4749
return;
4850

49-
impl_ = ref.impl_;
51+
impl_ = ref.impl_;
52+
m_data = ref.m_data;
5053
incrementWeak();
5154
}
5255

5356
CWeakPointer(const CWeakPointer& ref) noexcept {
5457
if (!ref.impl_)
5558
return;
5659

57-
impl_ = ref.impl_;
60+
impl_ = ref.impl_;
61+
m_data = ref.m_data;
5862
incrementWeak();
5963
}
6064

6165
template <typename U, typename = isConstructible<U>>
6266
CWeakPointer(CWeakPointer<U>&& ref) noexcept {
6367
std::swap(impl_, ref.impl_);
68+
std::swap(m_data, ref.m_data);
6469
}
6570

6671
CWeakPointer(CWeakPointer&& ref) noexcept {
6772
std::swap(impl_, ref.impl_);
73+
std::swap(m_data, ref.m_data);
6874
}
6975

7076
/* create a weak ptr from another weak ptr with assignment */
@@ -74,7 +80,8 @@ namespace Hyprutils {
7480
return *this;
7581

7682
decrementWeak();
77-
impl_ = rhs.impl_;
83+
impl_ = rhs.impl_;
84+
m_data = rhs.m_data;
7885
incrementWeak();
7986
return *this;
8087
}
@@ -84,7 +91,8 @@ namespace Hyprutils {
8491
return *this;
8592

8693
decrementWeak();
87-
impl_ = rhs.impl_;
94+
impl_ = rhs.impl_;
95+
m_data = rhs.m_data;
8896
incrementWeak();
8997
return *this;
9098
}
@@ -96,7 +104,8 @@ namespace Hyprutils {
96104
return *this;
97105

98106
decrementWeak();
99-
impl_ = rhs.impl_;
107+
impl_ = rhs.impl_;
108+
m_data = rhs.m_data;
100109
incrementWeak();
101110
return *this;
102111
}
@@ -125,14 +134,15 @@ namespace Hyprutils {
125134

126135
void reset() {
127136
decrementWeak();
128-
impl_ = nullptr;
137+
impl_ = nullptr;
138+
m_data = nullptr;
129139
}
130140

131141
CSharedPointer<T> lock() const {
132142
if (!impl_ || !impl_->dataNonNull() || impl_->destroying() || !impl_->lockable())
133143
return {};
134144

135-
return CSharedPointer<T>(impl_);
145+
return CSharedPointer<T>(impl_, m_data);
136146
}
137147

138148
/* this returns valid() */
@@ -169,7 +179,7 @@ namespace Hyprutils {
169179
}
170180

171181
T* get() const {
172-
return impl_ ? sc<T*>(impl_->getData()) : nullptr;
182+
return impl_ && impl_->dataNonNull() ? sc<T*>(m_data) : nullptr;
173183
}
174184

175185
T* operator->() const {
@@ -182,6 +192,9 @@ namespace Hyprutils {
182192

183193
Impl_::impl_base* impl_ = nullptr;
184194

195+
// Never use directly: raw data ptr, could be UAF
196+
void* m_data = nullptr;
197+
185198
private:
186199
/* no-op if there is no impl_ */
187200
void decrementWeak() {

0 commit comments

Comments
 (0)