From 664cec006f3b19b190279148085eeda79511f5a8 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 19 Oct 2026 18:44:13 -0700 Subject: [PATCH] Protect library directory and shared buffer access Move the library directory and shared vertex/index buffer handles into the protected source and rendering groups. Expose one GetBuffers accessor returning const references to both buffers, and use structured binding in BindMesh while preserving GL binding and uncached-mesh fallback behavior. Add GetLibraryFilePath for mapping-file lookups and update the LXF and BrickLink callers. Keep file opening and bundled-resource fallback in those callers so the library only resolves the path and exposes no mutable directory state. Validation: warning-free macOS Qt 6.10 Debug build, all 45 offscreen lifecycle checks and diff whitespace checks pass. No remaining external field accesses for the protected directory or buffers. GPU rendering was not tested. --- common/lc_bricklink.cpp | 2 +- common/lc_context.cpp | 7 +++---- common/lc_library.h | 24 +++++++++++++++++------- common/lc_lxf.cpp | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/common/lc_bricklink.cpp b/common/lc_bricklink.cpp index 712d386d..20c58039 100644 --- a/common/lc_bricklink.cpp +++ b/common/lc_bricklink.cpp @@ -11,7 +11,7 @@ static QJsonDocument lcLoadBrickLinkMapping() { std::map Remapping; - QFile File(lcGetPiecesLibrary()->mLibraryDir.absoluteFilePath(QLatin1String("ldraw2bl.txt"))); + QFile File(lcGetPiecesLibrary()->GetLibraryFilePath(QLatin1String("ldraw2bl.txt"))); QByteArray Data; if (File.open(QIODevice::ReadOnly)) diff --git a/common/lc_context.cpp b/common/lc_context.cpp index a55c106b..7813647e 100644 --- a/common/lc_context.cpp +++ b/common/lc_context.cpp @@ -1519,12 +1519,11 @@ void lcContext::SetIndexBufferPointer(const void* IndexBuffer) void lcContext::BindMesh(const lcMesh* Mesh) { - const lcPiecesLibrary* const Library = lcGetPiecesLibrary(); - if (Mesh->mVertexCacheOffset != -1) { - const GLuint VertexBufferObject = Library->mVertexBuffer.Object; - const GLuint IndexBufferObject = Library->mIndexBuffer.Object; + const auto [VertexBuffer, IndexBuffer] = lcGetPiecesLibrary()->GetBuffers(); + const GLuint VertexBufferObject = VertexBuffer.Object; + const GLuint IndexBufferObject = IndexBuffer.Object; if (VertexBufferObject != mVertexBufferObject) { diff --git a/common/lc_library.h b/common/lc_library.h index 9e35204d..6deeb642 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -145,6 +145,12 @@ public: // Loads the bundled fallback library and its default settings. bool LoadBuiltinPieceLibrary(); + // Resolves a file path relative to the library directory without opening it. + QString GetLibraryFilePath(const QString& FileName) const + { + return mLibraryDir.absoluteFilePath(FileName); + } + // Returns the official archive count for update checks, or zero for custom/directory libraries. int GetOfficialPieceCount() const { @@ -292,17 +298,18 @@ public: // Rebuilds shared mesh buffers when dirty, using the supplied render context. void UpdateBuffers(lcContext* Context); + // Returns borrowed read-only references to the shared vertex and index buffers. + std::pair GetBuffers() const + { + return { mVertexBuffer, mIndexBuffer }; + } + // Checks unused library parts under the existing zero-reference release policy. void UnloadUnusedParts(); // Returns the borrowed placeholder mesh for pending or failed piece geometry. lcMesh* GetLoadingMesh() const; - QDir mLibraryDir; - - lcVertexBuffer mVertexBuffer; - lcIndexBuffer mIndexBuffer; - signals: void AssetStatusChanged(); void PartLoaded(lcPieceData* PieceData); @@ -396,7 +403,8 @@ protected: void ReleaseBuffers(); - // Archive readers and discovered primitive sources; workers drain before replacement or teardown. + // Library directory, archive readers and primitive sources; workers drain before replacement or teardown. + QDir mLibraryDir; std::unique_ptr mZipFiles[static_cast(lcZipFileType::Count)]; std::vector> mSources; bool mHasUnofficial; @@ -432,7 +440,9 @@ protected: QString mCachePath; qint64 mArchiveCheckSum[4]; - // Placeholder geometry and deferred shared-buffer repacking state. + // Shared GPU buffers, placeholder geometry and deferred repacking state. + lcVertexBuffer mVertexBuffer; + lcIndexBuffer mIndexBuffer; bool mBuffersDirty; std::unique_ptr mLoadingMesh; bool mStreamingBuffersPending = false; diff --git a/common/lc_lxf.cpp b/common/lc_lxf.cpp index 805b6c67..ef05463e 100644 --- a/common/lc_lxf.cpp +++ b/common/lc_lxf.cpp @@ -9,7 +9,7 @@ static bool lcLoadLDrawXML(std::map& MaterialTable, std::map& BrickTable, std::map>& TransformTable) { - QFile File(lcGetPiecesLibrary()->mLibraryDir.absoluteFilePath(QLatin1String("ldraw.xml"))); + QFile File(lcGetPiecesLibrary()->GetLibraryFilePath(QLatin1String("ldraw.xml"))); QByteArray Data; if (File.open(QIODevice::ReadOnly))