[ox/mc] Cleanup, fix possible overflow bug
All checks were successful
Build / build (push) Successful in 1m8s

This commit is contained in:
2026-01-26 00:46:30 -06:00
parent 56c19ad2a6
commit 46a7331754
3 changed files with 44 additions and 42 deletions

View File

@@ -11,7 +11,7 @@
namespace ox { namespace ox {
template class FieldBitmapWriterBase<uint8_t*>; template class FieldBitmapWriterBase<uint8_t>;
template class FieldBitmapWriterBase<const uint8_t*>; template class FieldBitmapWriterBase<uint8_t const>;
} }

View File

@@ -11,6 +11,7 @@
#include <ox/std/array.hpp> #include <ox/std/array.hpp>
#include <ox/std/bit.hpp> #include <ox/std/bit.hpp>
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/span.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include <ox/std/reader.hpp> #include <ox/std/reader.hpp>
@@ -21,18 +22,18 @@ namespace ox {
template<Reader_c Reader> template<Reader_c Reader>
class FieldBitmapReader { class FieldBitmapReader {
protected: protected:
mutable std::size_t m_mapBlockIdx = ~std::size_t{0}; mutable size_t m_mapBlockIdx = ~size_t{0};
mutable uint64_t m_mapBlock = 0; mutable uint64_t m_mapBlock = 0;
std::size_t m_mapStart = 0; size_t m_mapStart = 0;
Reader &m_reader; Reader &m_reader;
public: public:
explicit constexpr FieldBitmapReader(Reader &reader) noexcept; explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept; constexpr Result<bool> get(size_t idx) const noexcept;
private: private:
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept; constexpr Error loadMapBlock(size_t idx) const noexcept;
}; };
@@ -43,7 +44,7 @@ constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept { constexpr Result<bool> FieldBitmapReader<Reader>::get(size_t idx) const noexcept {
constexpr auto blockBits = sizeof(m_mapBlock); constexpr auto blockBits = sizeof(m_mapBlock);
auto const blockIdx = idx / blockBits; auto const blockIdx = idx / blockBits;
if (m_mapBlockIdx != blockIdx) [[unlikely]] { if (m_mapBlockIdx != blockIdx) [[unlikely]] {
@@ -54,15 +55,15 @@ constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noe
} }
template<Reader_c Reader> template<Reader_c Reader>
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept { constexpr Error FieldBitmapReader<Reader>::loadMapBlock(size_t const idx) const noexcept {
OX_REQUIRE(g, m_reader.tellg()); OX_REQUIRE(g, m_reader.tellg());
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
ox::Array<char, sizeof(m_mapBlock)> mapBlock{}; Array<char, sizeof(m_mapBlock)> mapBlock{};
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock))); OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
// Warning: narrow-conv // Warning: narrow-conv
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg)); OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
m_mapBlock = 0; m_mapBlock = 0;
for (auto i = 0ull; auto b : mapBlock) { for (uint64_t i{}; auto b : mapBlock) {
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i; m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
i += 8; i += 8;
} }
@@ -74,17 +75,17 @@ constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) con
template<typename T> template<typename T>
class FieldBitmapWriterBase { class FieldBitmapWriterBase {
protected: protected:
T m_map = nullptr; Span<T> m_map;
std::size_t m_mapLen = 0; size_t m_mapLen = 0;
public: public:
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept; explicit constexpr FieldBitmapWriterBase(Span<T> map) noexcept;
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept; constexpr auto setBuffer(Span<T> map) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept; constexpr Result<bool> get(size_t i) const noexcept;
constexpr void setFields(int) noexcept; constexpr Error setFields(int) noexcept;
constexpr void setMaxLen(int) noexcept; constexpr void setMaxLen(int) noexcept;
@@ -94,34 +95,38 @@ class FieldBitmapWriterBase {
}; };
template<typename T> template<typename T>
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept { constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(Span<T> map) noexcept:
m_map = map; m_map(map),
m_mapLen = maxLen; m_mapLen(m_map.size()) {
} }
template<typename T> template<typename T>
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept { constexpr auto FieldBitmapWriterBase<T>::setBuffer(Span<T> map) noexcept {
m_map = map; m_map = map;
m_mapLen = maxLen; m_mapLen = map.size();
} }
template<typename T> template<typename T>
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept { constexpr Result<bool> FieldBitmapWriterBase<T>::get(size_t const i) const noexcept {
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
return (m_map[i / 8] >> (i % 8)) & 1; return (m_map[i / 8] >> (i % 8)) & 1;
} else { } else {
return ox::Error(McPresenceMapOverflow); return Error{McPresenceMapOverflow};
} }
} }
template<typename T> template<typename T>
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept { constexpr Error FieldBitmapWriterBase<T>::setFields(int const fields) noexcept {
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0)); m_mapLen = static_cast<size_t>((fields / 8 + 1) - (fields % 8 == 0));
if (m_mapLen > m_map.size()) [[unlikely]] {
return Error{McPresenceMapOverflow};
}
return {};
} }
template<typename T> template<typename T>
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept { constexpr void FieldBitmapWriterBase<T>::setMaxLen(int const maxLen) noexcept {
m_mapLen = static_cast<std::size_t>(maxLen); m_mapLen = static_cast<size_t>(maxLen);
} }
template<typename T> template<typename T>
@@ -129,34 +134,32 @@ constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
return static_cast<int64_t>(m_mapLen); return static_cast<int64_t>(m_mapLen);
} }
extern template class FieldBitmapWriterBase<uint8_t*>; extern template class FieldBitmapWriterBase<uint8_t>;
extern template class FieldBitmapWriterBase<const uint8_t*>; extern template class FieldBitmapWriterBase<uint8_t const>;
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> { class FieldBitmap: public FieldBitmapWriterBase<uint8_t> {
public: public:
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept; explicit constexpr FieldBitmap(Span<uint8_t> map) noexcept;
constexpr Error set(std::size_t i, bool on) noexcept; constexpr Error set(size_t i, bool on) noexcept;
}; };
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept: constexpr FieldBitmap::FieldBitmap(Span<uint8_t> map) noexcept:
FieldBitmapWriterBase<uint8_t*>(map, maxLen) { FieldBitmapWriterBase(map) {
} }
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept { constexpr Error FieldBitmap::set(size_t const i, bool const on) noexcept {
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (on) { if (on) {
m_map[i / 8] |= 1 << (i % 8); m_map[i / 8] |= 1 << (i % 8);
} else { } else {
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8)); m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
} }
OX_ALLOW_UNSAFE_BUFFERS_END
return {}; return {};
} else { } else {
return ox::Error(McPresenceMapOverflow); return Error(McPresenceMapOverflow);
} }
} }

View File

@@ -132,7 +132,7 @@ extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
template<Writer_c Writer> template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept: constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()), m_fieldPresence(m_presenceMapBuff),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_writerBeginP(writer.tellp()), m_writerBeginP(writer.tellp()),
m_writer(writer) { m_writer(writer) {
@@ -369,9 +369,8 @@ constexpr Error MetalClawWriter<Writer>::setTypeInfo(
auto const fieldPresenceLen = (fields - 1) / 8 + 1; auto const fieldPresenceLen = (fields - 1) / 8 + 1;
OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff);
m_fieldPresence.setFields(static_cast<int>(fields)); return m_fieldPresence.setFields(static_cast<int>(fields));
return {};
} }
template<Writer_c Writer> template<Writer_c Writer>