From 9c4315ff95f4cbfa86f65e292a45ec71d9ac9468 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Sun, 10 Mar 2024 09:46:53 +0000 Subject: [PATCH] [*] Hardening in the form of the prevention of future bad rewrites of similar code [+] MemoryView::AtOffset [+] MemoryView::Take --- Include/Aurora/Memory/ByteBuffer.hpp | 34 +----- Include/Aurora/Memory/MemoryView.hpp | 156 +++++++++++++++++++++------ 2 files changed, 126 insertions(+), 64 deletions(-) diff --git a/Include/Aurora/Memory/ByteBuffer.hpp b/Include/Aurora/Memory/ByteBuffer.hpp index 62e416ad..7c01a4f6 100644 --- a/Include/Aurora/Memory/ByteBuffer.hpp +++ b/Include/Aurora/Memory/ByteBuffer.hpp @@ -648,28 +648,13 @@ namespace Aurora::Memory inline AuSPtr ToSharedWriteView() { MemoryViewWrite view = *this; - struct View : MemoryViewWrite - { - View(MemoryViewWrite &&in) : MemoryViewWrite(in) - { } - - ~View() - { - this->ResetControlBlock(); - AuResetMember(this->pin); - } - - AuSPtr pin; - }; - if (!view) { return {}; } - if (auto pView = AuMakeShared(AuMove(view))) + if (auto pView = AuMakeShared(view.ptr, view.length, &this->uInUseCounter, AuSharedFromThis())) { - pView->pin = AuSharedFromThis(); return pView; } else @@ -681,28 +666,13 @@ namespace Aurora::Memory inline AuSPtr ToSharedReadView() { MemoryViewRead view = *this; - struct View : MemoryViewRead - { - View(MemoryViewRead &&in) : MemoryViewRead(in) - { } - - ~View() - { - this->ResetControlBlock(); - AuResetMember(this->pin); - } - - AuSPtr pin; - }; - if (!view) { return {}; } - if (auto pView = AuMakeShared(AuMove(view))) + if (auto pView = AuMakeShared(view.ptr, view.length, &this->uInUseCounter, AuSharedFromThis())) { - pView->pin = AuSharedFromThis(); return pView; } else diff --git a/Include/Aurora/Memory/MemoryView.hpp b/Include/Aurora/Memory/MemoryView.hpp index 9cd7de69..e3cf4b2e 100644 --- a/Include/Aurora/Memory/MemoryView.hpp +++ b/Include/Aurora/Memory/MemoryView.hpp @@ -11,7 +11,21 @@ namespace Aurora::Memory { struct MemoryControlBlock { + // Free-after-use mitigator: ensures a non-zero flag is kept whilst other memory views are present + // This helps mitigate: + // -> Take view from object + // -> Make view shared + // -> Pass off shared view to another subsystem + // -> Use the aforementioned object to resize, release, or do something bad with the memory pointed to by the initial view + // Mitgation: SysAssert(!pObject->uInUse) AuAUInt32 *pInUseCounter {}; + + // Mitigation (cont) and reducing code reuse: + // -> Allow for [shared!] memory views to have a shared freestanding owner + // -> Ensure reference counters or other forms of memory management don't free the owner before us + // (Consider inverse construction order, for instance, we'd have to always call MemoryView::ResetControlBlock() + // in a derived subclass, in order release the pInUseCounter reference before the derived shared members get released) + AuSPtr pPinner; // WARNING: as usual, std types don't validate their allocator, and our shared ptrs can be different between binaries! }; template @@ -62,6 +76,7 @@ namespace Aurora::Memory { AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); } + this->controlBlock.pPinner = view.controlBlock.pPinner; } MemoryView(MemoryView &&view) @@ -69,38 +84,10 @@ namespace Aurora::Memory this->ptr = view.ptr; this->length = view.length; this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner); view.controlBlock.pInUseCounter = nullptr; } - ~MemoryView() - { - if (controlBlock.pInUseCounter) - { - AuAtomicSub(controlBlock.pInUseCounter, 1u); - } - } - - MemoryView &operator =(MemoryView &&view) - { - this->ptr = view.ptr; - this->length = view.length; - this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; - view.controlBlock.pInUseCounter = nullptr; - return *this; - } - - MemoryView &operator =(const MemoryView &view) - { - this->ptr = view.ptr; - this->length = view.length; - this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; - if (this->controlBlock.pInUseCounter) - { - AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); - } - return *this; - } - template constexpr MemoryView(T(&a)[Z]) { @@ -139,6 +126,24 @@ namespace Aurora::Memory AuAtomicAdd(pInUseCounter, 1u); } + template + constexpr MemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner) + { + this->ptr = start; + if constexpr (AuIsSame_v) + { + this->length = reinterpret_cast(end) - reinterpret_cast(start); + } + else + { + this->length = (end - start) * sizeof(T); + } + + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pPinner = pRAIIOwner; + } + template constexpr MemoryView(T *start, AuUInt length) // WARNING: length != count // where T = whogivesafuck @@ -156,6 +161,58 @@ namespace Aurora::Memory AuAtomicAdd(pInUseCounter, 1u); } + template + constexpr MemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner) // WARNING: length != count + { + this->ptr = start; + this->length = length; + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pPinner = pRAIIOwner; + } + + ~MemoryView() + { + this->ResetControlBlock(); + } + + private: + template + MemoryView(T *start, AuUInt length, const MemoryControlBlock ©Block) + { + this->ptr = start; + this->length = length; + this->controlBlock = copyBlock; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } + } + public: + + MemoryView &operator =(MemoryView &&view) + { + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + view.controlBlock.pInUseCounter = nullptr; + this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner); + return *this; + } + + MemoryView &operator =(const MemoryView &view) + { + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } + this->controlBlock.pPinner = view.controlBlock.pPinner; + return *this; + } + AuUInt ToPointerValue() const { return reinterpret_cast(this->ptr); @@ -191,7 +248,7 @@ namespace Aurora::Memory operator bool() const { - return HasMemory(); + return this->HasMemory(); } U8_t ToPointer() const @@ -219,8 +276,41 @@ namespace Aurora::Memory return reinterpret_cast(this->ptr) + this->length; } - Void_t /*const*/ ptr; - AuUInt /*const*/ length; + MemoryView AtOffset(AuUInt uOffset) + { + if (uOffset < this->uLength) + { + return MemoryView(this->pBase + uOffset, this->uLength - uOffset, this->controlBlock); + } + else + { + return {}; + } + } + + MemoryView Take(AuUInt uLength) + { + if (uLength <= this->uLength) + { + return MemoryView(this->pBase, uLength, this->controlBlock); + } + else + { + return {}; + } + } + + union + { + Void_t /*const*/ ptr; + Void_t /*const*/ pBase; + }; + union + { + AuUInt /*const*/ length; + AuUInt /*const*/ uLength; + }; + private: MemoryControlBlock controlBlock; @@ -231,6 +321,8 @@ namespace Aurora::Memory { AuAtomicSub(pCounter, 1u); } + + AuResetMember(this->controlBlock.pPinner); } };