From 1735af21a4c7e0a78ac9d0b5fc193b61680b7067 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Wed, 11 Dec 2024 09:50:19 -0800 Subject: [PATCH] Fix crash when iterating empty type Summary: This diff fixes a crash when iterating the type of an entity without components, like here: ``` flecs::entity e = world.entity(); for (auto id : e.type()) { // crash } ``` Differential Revision: D67102905 --- distr/flecs.h | 17 ++++++++++---- include/flecs/addons/cpp/type.hpp | 17 ++++++++++---- test/cpp/project.json | 4 +++- test/cpp/src/Entity.cpp | 38 +++++++++++++++++++++++++++++++ test/cpp/src/main.cpp | 12 +++++++++- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/distr/flecs.h b/distr/flecs.h index d8f1b7e771..86906bd22a 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -27821,12 +27821,20 @@ struct type { return flecs::id(world_, type_->array[index]); } - flecs::id_t* begin() const { - return type_->array; + const flecs::id_t* begin() const { + if (type_ && type_->count) { + return type_->array; + } else { + return &empty_; + } } - flecs::id_t* end() const { - return &type_->array[type_->count]; + const flecs::id_t* end() const { + if (type_ && type_->count) { + return &type_->array[type_->count]; + } else { + return &empty_; + } } /** Implicit conversion to type_t */ @@ -27836,6 +27844,7 @@ struct type { private: world_t *world_; const type_t *type_; + flecs::id_t empty_; }; /** #} */ diff --git a/include/flecs/addons/cpp/type.hpp b/include/flecs/addons/cpp/type.hpp index 8a903fc4cb..ceef4aa14e 100644 --- a/include/flecs/addons/cpp/type.hpp +++ b/include/flecs/addons/cpp/type.hpp @@ -56,12 +56,20 @@ struct type { return flecs::id(world_, type_->array[index]); } - flecs::id_t* begin() const { - return type_->array; + const flecs::id_t* begin() const { + if (type_ && type_->count) { + return type_->array; + } else { + return &empty_; + } } - flecs::id_t* end() const { - return &type_->array[type_->count]; + const flecs::id_t* end() const { + if (type_ && type_->count) { + return &type_->array[type_->count]; + } else { + return &empty_; + } } /** Implicit conversion to type_t */ @@ -71,6 +79,7 @@ struct type { private: world_t *world_; const type_t *type_; + flecs::id_t empty_; }; /** #} */ diff --git a/test/cpp/project.json b/test/cpp/project.json index 73579eb99e..7391beeb15 100644 --- a/test/cpp/project.json +++ b/test/cpp/project.json @@ -296,7 +296,9 @@ "get_mut_pair_second_invalid_type", "ensure_pair_second_invalid_type", "set_pair_second_invalid_type", - "get_ref_pair_second_invalid_type" + "get_ref_pair_second_invalid_type", + "iter_type", + "iter_empty_type" ] }, { "id": "Pairs", diff --git a/test/cpp/src/Entity.cpp b/test/cpp/src/Entity.cpp index 7b03b7c628..979c9c809c 100644 --- a/test/cpp/src/Entity.cpp +++ b/test/cpp/src/Entity.cpp @@ -4863,3 +4863,41 @@ void Entity_get_ref_pair_second_invalid_type(void) { test_expect_abort(); world.entity().get_ref_second(v); } + +void Entity_iter_type(void) { + flecs::world world; + + flecs::entity e = world.entity().add().add(); + + int32_t count = 0; + bool pos_found = false; + bool velocity_found = false; + + for (auto id : e.type()) { + count ++; + if (id == world.id()) { + pos_found = true; + } + if (id == world.id()) { + velocity_found = true; + } + } + + test_int(count, 2); + test_assert(pos_found == true); + test_assert(velocity_found == true); +} + +void Entity_iter_empty_type(void) { + flecs::world world; + + flecs::entity e = world.entity(); + + int32_t count = 0; + + for (auto id : e.type()) { + count ++; + } + + test_int(count, 0); +} diff --git a/test/cpp/src/main.cpp b/test/cpp/src/main.cpp index 7a5c45ac9d..b75c920aa7 100644 --- a/test/cpp/src/main.cpp +++ b/test/cpp/src/main.cpp @@ -289,6 +289,8 @@ void Entity_get_mut_pair_second_invalid_type(void); void Entity_ensure_pair_second_invalid_type(void); void Entity_set_pair_second_invalid_type(void); void Entity_get_ref_pair_second_invalid_type(void); +void Entity_iter_type(void); +void Entity_iter_empty_type(void); // Testsuite 'Pairs' void Pairs_add_component_pair(void); @@ -2520,6 +2522,14 @@ bake_test_case Entity_testcases[] = { { "get_ref_pair_second_invalid_type", Entity_get_ref_pair_second_invalid_type + }, + { + "iter_type", + Entity_iter_type + }, + { + "iter_empty_type", + Entity_iter_empty_type } }; @@ -6882,7 +6892,7 @@ static bake_test_suite suites[] = { "Entity", NULL, NULL, - 276, + 278, Entity_testcases }, {