From c97df7d7708b6b5e50da3377967ad379a7175675 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 20 Apr 2023 02:12:56 +0200 Subject: [PATCH] Check FormIdRefId value in constructor --- apps/openmw_test_suite/esm/testrefid.cpp | 5 +++++ components/esm/formidrefid.cpp | 17 +++++++++++------ components/esm/formidrefid.hpp | 5 ++++- components/esm/refid.hpp | 4 ++-- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/apps/openmw_test_suite/esm/testrefid.cpp b/apps/openmw_test_suite/esm/testrefid.cpp index 8e25ddbb6d..11ac7a6477 100644 --- a/apps/openmw_test_suite/esm/testrefid.cpp +++ b/apps/openmw_test_suite/esm/testrefid.cpp @@ -177,6 +177,11 @@ namespace ESM EXPECT_FALSE(formIdRefId < stringView); } + TEST(ESMRefIdTest, formIdRefIdIndexShouldHaveOnly24SignificantBits) + { + EXPECT_THROW(FormIdRefId(FormId{ .mIndex = 1 << 25, .mContentFile = 0 }), std::invalid_argument); + } + TEST(ESMRefIdTest, canBeUsedAsMapKeyWithLookupByStringView) { const std::map> map({ { RefId::stringRefId("a"), 42 } }); diff --git a/components/esm/formidrefid.cpp b/components/esm/formidrefid.cpp index 8e452d6ecd..d8d049d203 100644 --- a/components/esm/formidrefid.cpp +++ b/components/esm/formidrefid.cpp @@ -1,18 +1,24 @@ #include "formidrefid.hpp" -#include #include #include "serializerefid.hpp" namespace ESM { + namespace + { + std::uint64_t truncate(FormId value) + { + return (static_cast(value.mContentFile) << 24) | value.mIndex; + } + } + std::string FormIdRefId::toString() const { std::string result; - assert((mValue.mIndex & 0xff000000) == 0); - size_t v = (static_cast(mValue.mContentFile) << 24) | mValue.mIndex; - result.resize(getHexIntegralSize(v) + 2, '\0'); + const std::uint64_t v = truncate(mValue); + result.resize(getHexIntegralSizeWith0x(v), '\0'); serializeHexIntegral(v, 0, result); return result; } @@ -20,8 +26,7 @@ namespace ESM std::string FormIdRefId::toDebugString() const { std::string result; - assert((mValue.mIndex & 0xff000000) == 0); - size_t v = (static_cast(mValue.mContentFile) << 24) | mValue.mIndex; + const std::uint64_t v = truncate(mValue); serializeRefIdValue(v, formIdRefIdPrefix, result); return result; } diff --git a/components/esm/formidrefid.hpp b/components/esm/formidrefid.hpp index 176dc4ec84..10db8c918b 100644 --- a/components/esm/formidrefid.hpp +++ b/components/esm/formidrefid.hpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -13,9 +14,11 @@ namespace ESM public: constexpr FormIdRefId() = default; - constexpr explicit FormIdRefId(ESM::FormId value) noexcept + constexpr explicit FormIdRefId(ESM::FormId value) : mValue(value) { + if ((mValue.mIndex & 0xff000000) != 0) + throw std::invalid_argument("Invalid FormIdRefId index value: " + std::to_string(mValue.mIndex)); } ESM::FormId getValue() const { return mValue; } diff --git a/components/esm/refid.hpp b/components/esm/refid.hpp index 170db6791d..d1cd5901bf 100644 --- a/components/esm/refid.hpp +++ b/components/esm/refid.hpp @@ -63,7 +63,7 @@ namespace ESM static RefId stringRefId(std::string_view value); // Constructs RefId from FormId storing the value in-place. - static RefId formIdRefId(FormId value) noexcept { return RefId(FormIdRefId(value)); } + static RefId formIdRefId(FormId value) { return RefId(FormIdRefId(value)); } // Constructs RefId from uint64 storing the value in-place. Should be used for generated records where id is a // global counter. @@ -87,7 +87,7 @@ namespace ESM { } - constexpr RefId(FormIdRefId value) noexcept + constexpr RefId(FormIdRefId value) : mValue(value) { }