From 03f45febe2044d16b82f8e5c791aea108daaf50c Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 18 Sep 2020 16:13:41 -0600 Subject: [PATCH] Kernel: Fix KResultOr move semantics We need to track whether we actually own the storage. --- Kernel/KResult.h | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/Kernel/KResult.h b/Kernel/KResult.h index cb457b09f1..94e86961e9 100644 --- a/Kernel/KResult.h +++ b/Kernel/KResult.h @@ -72,12 +72,14 @@ public: ALWAYS_INLINE KResultOr(T&& value) { new (&m_storage) T(move(value)); + m_have_storage = true; } template ALWAYS_INLINE KResultOr(U&& value) { new (&m_storage) T(move(value)); + m_have_storage = true; } KResultOr(KResultOr&& other) @@ -86,8 +88,12 @@ public: if (m_is_error) m_error = other.m_error; else { - new (&m_storage) T(move(other.value())); - other.value().~T(); + if (other.m_have_storage) { + new (&m_storage) T(move(other.value())); + m_have_storage = true; + other.value().~T(); + other.m_have_storage = false; + } } other.m_is_error = true; other.m_error = KSuccess; @@ -95,14 +101,20 @@ public: KResultOr& operator=(KResultOr&& other) { - if (!m_is_error) + if (!m_is_error && m_have_storage) { value().~T(); + m_have_storage = false; + } m_is_error = other.m_is_error; if (m_is_error) m_error = other.m_error; else { - new (&m_storage) T(move(other.value())); - other.value().~T(); + if (other.m_have_storage) { + new (&m_storage) T(move(other.value())); + m_have_storage = true; + other.value().~T(); + other.m_have_storage = false; + } } other.m_is_error = true; other.m_error = KSuccess; @@ -111,7 +123,7 @@ public: ~KResultOr() { - if (!m_is_error) + if (!m_is_error && m_have_storage) value().~T(); } @@ -140,8 +152,10 @@ public: ALWAYS_INLINE T release_value() { ASSERT(!m_is_error); + ASSERT(m_have_storage); T released_value = *reinterpret_cast(&m_storage); value().~T(); + m_have_storage = false; return released_value; } @@ -149,6 +163,7 @@ private: alignas(T) char m_storage[sizeof(T)]; KResult m_error; bool m_is_error { false }; + bool m_have_storage { false }; }; }