diff --git a/include/rfl/json/Reader.hpp b/include/rfl/json/Reader.hpp index 31c943fbe..855834f1d 100644 --- a/include/rfl/json/Reader.hpp +++ b/include/rfl/json/Reader.hpp @@ -7,7 +7,9 @@ #include "../thirdparty/yyjson.h" #endif +#include #include +#include #include #include #include @@ -166,13 +168,22 @@ struct Reader { if (!yyjson_is_uint(_var.val_)) { return error("Could not cast to uint."); } - return static_cast(yyjson_get_uint(_var.val_)); + const auto value = yyjson_get_uint(_var.val_); + if (value > static_cast(std::numeric_limits>::max())) { + return error("Integer is out of range for the target type."); + } + return static_cast(value); } else if constexpr (std::is_integral>()) { if (!yyjson_is_int(_var.val_)) { return error("Could not cast to int."); } - return static_cast(yyjson_get_sint(_var.val_)); + const auto value = yyjson_get_sint(_var.val_); + if (value < std::numeric_limits>::min() || + value > std::numeric_limits>::max()) { + return error("Integer is out of range for the target type."); + } + return static_cast(value); } else { static_assert(rfl::always_false_v, "Unsupported type."); diff --git a/tests/json/test_integers.cpp b/tests/json/test_integers.cpp index f0ebc4dd1..0a1ea8a28 100644 --- a/tests/json/test_integers.cpp +++ b/tests/json/test_integers.cpp @@ -6,6 +6,23 @@ namespace test_integers { +TEST(json, test_narrow_integer_bounds) { + struct NarrowIntegers { + int16_t signed_value; + uint16_t unsigned_value; + }; + + write_and_read(NarrowIntegers{.signed_value = INT16_MIN, + .unsigned_value = UINT16_MAX}, + R"({"signed_value":-32768,"unsigned_value":65535})"); + EXPECT_FALSE(rfl::json::read( + R"({"signed_value":32768,"unsigned_value":1})")); + EXPECT_FALSE(rfl::json::read( + R"({"signed_value":-32769,"unsigned_value":1})")); + EXPECT_FALSE(rfl::json::read( + R"({"signed_value":0,"unsigned_value":100200})")); +} + TEST(json, test_integers) { struct Integers {