From 1482adeaae5b09b4afae8c2c98656f9c641aa633 Mon Sep 17 00:00:00 2001 From: ChrisHal Date: Fri, 6 Dec 2024 21:09:37 +0100 Subject: [PATCH] avoid type punning and problematic reinterpret_cast --- hekatoolslib/hkTree.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/hekatoolslib/hkTree.cpp b/hekatoolslib/hkTree.cpp index 90f0acd..110d688 100644 --- a/hekatoolslib/hkTree.cpp +++ b/hekatoolslib/hkTree.cpp @@ -66,6 +66,7 @@ namespace hkLib { nLevels, //!< number of tree levels LevelSizes[1]; //!< variable length array (nLevels entries with size of level data in bytes) }; + constexpr auto TreeRootHeaderSize = offsetof(TreeRoot,LevelSizes); void hkLib::hkTree::LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, char* data_end, int level) { @@ -103,27 +104,28 @@ namespace hkLib { bool hkTree::InitFromBuffer(const std::string_view& id, char* buffer, std::size_t len) { - if (len < sizeof(TreeRoot)) throw std::runtime_error("invalid TreeRoot (too few bytes in file)"); + if (len < TreeRootHeaderSize) throw std::runtime_error("invalid TreeRoot (too few bytes in file)"); ID = id; - TreeRoot* root = reinterpret_cast(buffer); // we assume buffer is correctly aligned + TreeRoot root; + std::memcpy(&root, buffer, TreeRootHeaderSize); isSwapped = false; - if (root->Magic == SwappedMagicNumber) { + if (root.Magic == SwappedMagicNumber) { isSwapped = true; } - else if (root->Magic != MagicNumber) { + else if (root.Magic != MagicNumber) { throw std::runtime_error("magic number does not match, wrong filetype?"); } - LevelSizes.clear(); - if (isSwapped) { - swapInPlace(root->nLevels); + if (isSwapped) { + swapInPlace(root.nLevels); } - const auto root_bytes = offsetof(TreeRoot, LevelSizes) + sizeof(std::uint32_t) * root->nLevels; + const auto root_bytes = TreeRootHeaderSize + sizeof(std::uint32_t) * root.nLevels; if (len < root_bytes) throw std::runtime_error("invalid TreeRoot (too few bytes in file)"); - for (std::size_t i = 0; i < root->nLevels; ++i) { - if (isSwapped) { swapInPlace(root->LevelSizes[i]); } - LevelSizes.push_back(root->LevelSizes[i]); - } - char* data = buffer + root_bytes; // start of first tree node + LevelSizes.resize(root.nLevels); + std::memcpy(LevelSizes.data(), buffer + TreeRootHeaderSize, sizeof(std::uint32_t) * root.nLevels); + if(isSwapped){ + for(auto& l : LevelSizes) swapInPlace(l); + } + char* data = buffer + root_bytes; // start of first tree node LoadToNode(nullptr, RootNode, &data, buffer + len, 0); if (data - buffer != static_cast(len)) { throw std::runtime_error("bytes read != bytes in buffer");