Browse Source

meta: check traits before saving

Michele Caini 1 year ago
parent
commit
7acd6e7f53

+ 3 - 1
src/entt/meta/node.hpp

@@ -55,7 +55,9 @@ template<typename Type>
 [[nodiscard]] auto user_to_meta_traits(const Type value) noexcept {
     static_assert(std::is_enum_v<Type>, "Invalid enum type");
     constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits));
-    return meta_traits{static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Type>>(value)) << shift};
+    const auto traits = static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Type>>(value));
+    ENTT_ASSERT(traits < ((~static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)) >> shift), "Invalid traits");
+    return meta_traits{traits << shift};
 }
 
 struct meta_type_node;

+ 8 - 0
test/entt/meta/meta_data.cpp

@@ -203,6 +203,14 @@ TEST_F(MetaData, UserTraits) {
     ASSERT_EQ(entt::resolve<clazz>().data("k"_hs).traits<test::meta_traits>(), test::meta_traits::three);
 }
 
+ENTT_DEBUG_TEST_F(MetaDataDeathTest, UserTraits) {
+    using namespace entt::literals;
+
+    using traits_type = entt::internal::meta_traits;
+    constexpr auto value = traits_type{static_cast<std::underlying_type_t<traits_type>>(traits_type::_user_defined_traits) + 1u};
+    ASSERT_DEATH(entt::meta<clazz>().data<&clazz::i>("j"_hs).traits(value), "");
+}
+
 TEST_F(MetaData, Custom) {
     using namespace entt::literals;
 

+ 8 - 0
test/entt/meta/meta_func.cpp

@@ -218,6 +218,14 @@ TEST_F(MetaFunc, UserTraits) {
     ASSERT_EQ(entt::resolve<function>().func("f3"_hs).traits<test::meta_traits>(), test::meta_traits::three);
 }
 
+ENTT_DEBUG_TEST_F(MetaFuncDeathTest, UserTraits) {
+    using namespace entt::literals;
+
+    using traits_type = entt::internal::meta_traits;
+    constexpr auto value = traits_type{static_cast<std::underlying_type_t<traits_type>>(traits_type::_user_defined_traits) + 1u};
+    ASSERT_DEATH(entt::meta<function>().func<&function::g>("g"_hs).traits(value), "");
+}
+
 TEST_F(MetaFunc, Custom) {
     using namespace entt::literals;
 

+ 6 - 0
test/entt/meta/meta_type.cpp

@@ -289,6 +289,12 @@ TEST_F(MetaType, UserTraits) {
     ASSERT_EQ(entt::resolve<property_type>().traits<test::meta_traits>(), test::meta_traits::two | test::meta_traits::three);
 }
 
+ENTT_DEBUG_TEST_F(MetaTypeDeathTest, UserTraits) {
+    using traits_type = entt::internal::meta_traits;
+    constexpr auto value = traits_type{static_cast<std::underlying_type_t<traits_type>>(traits_type::_user_defined_traits) + 1u};
+    ASSERT_DEATH(entt::meta<clazz>().traits(value), "");
+}
+
 TEST_F(MetaType, Custom) {
     ASSERT_EQ(*static_cast<const char *>(entt::resolve<clazz>().custom()), 'c');
     ASSERT_EQ(static_cast<const char &>(entt::resolve<clazz>().custom()), 'c');