From 574189fb7d3297851a5d6e706ad8e58c1e536b60 Mon Sep 17 00:00:00 2001 From: Lixin Wei Date: Sun, 22 Mar 2026 23:28:32 +0800 Subject: [PATCH] Fix Cap'n Proto serialization of unsigned integer types The Writer was casting all integral types to std::int64_t, which causes uint64_t values like UINT64_MAX to overflow to -1 and trigger a Cap'n Proto assertion: "expected value >= 0". This adds a std::is_unsigned branch (before the std::is_integral fallback) in add_value_to_array, add_value_to_object, and add_value_to_union so unsigned types are cast to std::uint64_t instead. Made-with: Cursor --- include/rfl/capnproto/Writer.hpp | 10 ++++++++++ tests/capnproto/test_uint64.cpp | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/capnproto/test_uint64.cpp diff --git a/include/rfl/capnproto/Writer.hpp b/include/rfl/capnproto/Writer.hpp index c93f9621b..8d34f6b9c 100644 --- a/include/rfl/capnproto/Writer.hpp +++ b/include/rfl/capnproto/Writer.hpp @@ -171,6 +171,9 @@ class RFL_API Writer { std::is_same, bool>()) { _parent->val_.set(_parent->ix_++, _var); + } else if constexpr (std::is_unsigned>()) { + _parent->val_.set(_parent->ix_++, static_cast(_var)); + } else if constexpr (std::is_integral>()) { _parent->val_.set(_parent->ix_++, static_cast(_var)); @@ -211,6 +214,10 @@ class RFL_API Writer { std::is_same, bool>()) { _parent->val_.set(to_kj_string_ptr(_name), _var); + } else if constexpr (std::is_unsigned>()) { + _parent->val_.set(to_kj_string_ptr(_name), + static_cast(_var)); + } else if constexpr (std::is_integral>()) { _parent->val_.set(to_kj_string_ptr(_name), static_cast(_var)); @@ -242,6 +249,9 @@ class RFL_API Writer { std::is_same, bool>()) { _parent->val_.set(field, _var); + } else if constexpr (std::is_unsigned>()) { + _parent->val_.set(field, static_cast(_var)); + } else if constexpr (std::is_integral>()) { _parent->val_.set(field, static_cast(_var)); diff --git a/tests/capnproto/test_uint64.cpp b/tests/capnproto/test_uint64.cpp new file mode 100644 index 000000000..df43c478f --- /dev/null +++ b/tests/capnproto/test_uint64.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include "write_and_read.hpp" + +namespace test_uint64 { + +struct UnsignedStruct { + uint64_t x = UINT64_MAX; + uint32_t y = UINT32_MAX; + uint16_t z = UINT16_MAX; + uint8_t w = UINT8_MAX; +}; + +TEST(capnproto, test_uint64) { + const auto s = UnsignedStruct{}; + write_and_read(s); +} + +TEST(capnproto, test_uint64_specific_values) { + const auto s = UnsignedStruct{ + .x = 0, .y = 0, .z = 0, .w = 0}; + write_and_read(s); +} + +TEST(capnproto, test_uint64_max_values) { + const auto s = UnsignedStruct{ + .x = UINT64_MAX, .y = UINT32_MAX, .z = UINT16_MAX, .w = UINT8_MAX}; + write_and_read(s); +} + +} // namespace test_uint64