From 66fa3ff4bab5e36066784e61632e07336de7b8d5 Mon Sep 17 00:00:00 2001 From: jadebenn Date: Mon, 25 Nov 2024 01:40:58 -0600 Subject: [PATCH] created FromBitsUnchecked memcpy wrapper --- dCommon/GeneralUtils.h | 21 +++++++++++++++++++ dCommon/dClient/AssetManager.h | 1 + .../02_server/Map/AG/NpcAgCourseStarter.cpp | 9 ++++---- dWorldServer/WorldServer.cpp | 5 ++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/dCommon/GeneralUtils.h b/dCommon/GeneralUtils.h index 3c4ee285f..b1d497281 100644 --- a/dCommon/GeneralUtils.h +++ b/dCommon/GeneralUtils.h @@ -3,6 +3,7 @@ // C++ #include #include +#include #include #include #include @@ -152,6 +153,26 @@ namespace GeneralUtils { char_pointer_hash >; + /** + * A convenience wrapper around std::memcpy that creates a new object + * from the value representation of the provided bytes.Use when + * std::bit_cast is not applicable. + * @warning All restrictions of std::memcpy still apply. Accessing + * outside of the source object is undefined behavior. + * @param from The source of the value representation + * @returns A new object with the given value representation + */ + template + [[nodiscard]] + inline To FromBitsUnchecked(const From* from) noexcept + requires (std::is_trivially_copyable_v + && std::is_trivially_copyable_v) + { + To to{}; + std::memcpy(&to, from, sizeof(To)); + return to; + } + // Concept constraining to enum types template concept Enum = std::is_enum_v; diff --git a/dCommon/dClient/AssetManager.h b/dCommon/dClient/AssetManager.h index 2116f2237..73e6162a9 100644 --- a/dCommon/dClient/AssetManager.h +++ b/dCommon/dClient/AssetManager.h @@ -54,6 +54,7 @@ struct AssetStream : std::istream { } operator bool() { + // NEED TO FIX THIS return reinterpret_cast(rdbuf())->m_Success; } }; diff --git a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp index 5bd0ff2bd..c6c3629d9 100644 --- a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp +++ b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp @@ -81,11 +81,10 @@ void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); } else if (args == "course_finish") { const time_t endTime = std::time(0); - - // Using memcpy since misaligned reads are UB - time_t startTime{}; - std::memcpy(&startTime, &data->values[1], sizeof(time_t)); - const time_t finish = (endTime - startTime); + + // Using FromBitsUnchecked to create new time_t object since misaligned reads are UB + const time_t startTime = GeneralUtils::FromBitsUnchecked(&data->values[1]); + const time_t finish = endTime - startTime; std::memcpy(&data->values[2], &finish, sizeof(float)); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 84a0c1a93..c71c4a4fe 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1396,9 +1396,8 @@ void HandlePacket(Packet* packet) { } default: - // Need to use memcpy instead of reinterpret_cast to avoid misaligned reads, which are UB - auto messageId = MessageType::World::INVALID; - std::memcpy(&messageId, &packet->data[3], sizeof(MessageType::World)); + // Need to use FromBitsUnchecked (aka memcpy) instead of reinterpret_cast to avoid misaligned reads, which are UB + const auto messageId = GeneralUtils::FromBitsUnchecked(&packet->data[3]); const std::string_view messageIdString = StringifiedEnum::ToString(messageId); LOG("Unknown world packet received: %4i, %s", messageId, messageIdString.data());