From 631a1fd54aac1c986f1eb1398eeebfa881c6fe51 Mon Sep 17 00:00:00 2001 From: Rockjack00 Date: Thu, 5 Jun 2025 15:26:40 +0200 Subject: [PATCH 1/3] Added a check for recursive behavior trees while parsing --- src/xml_parsing.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index 8b9ce95a1..7ab24f033 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -10,6 +10,7 @@ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include @@ -934,8 +935,17 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID, } else // special case: SubTreeNode { - auto new_bb = Blackboard::create(blackboard); const std::string subtree_ID = element->Attribute("ID"); + + // check for recursion in behavior tree + if(prefix.find(subtree_ID) != std::string::npos) + { + auto msg = StrCat("Recursive behavior trees are not supported. A cycle was found in ", + " with prefix: ", prefix); + throw RuntimeError(msg); + } + + auto new_bb = Blackboard::create(blackboard); std::unordered_map subtree_remapping; bool do_autoremap = false; From 9858e9165d78e22fa3bb265d463fe63d2e7de7c2 Mon Sep 17 00:00:00 2001 From: Rockjack00 Date: Thu, 5 Jun 2025 15:27:22 +0200 Subject: [PATCH 2/3] Created tests for recursive behavior trees while parsing --- tests/gtest_subtree.cpp | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/gtest_subtree.cpp b/tests/gtest_subtree.cpp index 6402bafba..eb0908193 100644 --- a/tests/gtest_subtree.cpp +++ b/tests/gtest_subtree.cpp @@ -726,3 +726,67 @@ TEST(SubTree, SubtreeNameNotRegistered) ASSERT_ANY_THROW(auto tree = factory.createTreeFromText(xml_text)); ASSERT_ANY_THROW(factory.registerBehaviorTreeFromText(xml_text)); } + +TEST(SubTree, RecursiveSubtree) +{ + // clang-format off + + static const char* xml_text = R"( + + + + + + + + + + + )"; + + // clang-format on + BehaviorTreeFactory factory; + std::vector console; + factory.registerNodeType("PrintToConsole", &console); + + ASSERT_ANY_THROW(auto tree = factory.createTreeFromText(xml_text)); +} + +TEST(SubTree, RecursiveCycle) +{ + // clang-format off + + static const char* xml_text = R"( + + + + + + + + + + + + + + + + + + + + + + + + )"; + + // clang-format on + BehaviorTreeFactory factory; + std::vector console; + factory.registerNodeType("PrintToConsole", &console); + + ASSERT_ANY_THROW(auto tree = factory.createTreeFromText(xml_text)); +} + From 0f26b682193bec09f760b49ab168a0cd6d957b47 Mon Sep 17 00:00:00 2001 From: Rockjack00 Date: Thu, 5 Jun 2025 15:40:47 +0200 Subject: [PATCH 3/3] Code formatted --- src/xml_parsing.cpp | 3 +- tests/gtest_subtree.cpp | 64 +++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index 7ab24f033..a80f01444 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -940,7 +940,8 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID, // check for recursion in behavior tree if(prefix.find(subtree_ID) != std::string::npos) { - auto msg = StrCat("Recursive behavior trees are not supported. A cycle was found in ", + auto msg = StrCat("Recursive behavior trees are not supported. A cycle was found " + "in ", " with prefix: ", prefix); throw RuntimeError(msg); } diff --git a/tests/gtest_subtree.cpp b/tests/gtest_subtree.cpp index eb0908193..26312b10d 100644 --- a/tests/gtest_subtree.cpp +++ b/tests/gtest_subtree.cpp @@ -732,16 +732,14 @@ TEST(SubTree, RecursiveSubtree) // clang-format off static const char* xml_text = R"( - - - - - - - - - - + + + + + + + + )"; // clang-format on @@ -757,29 +755,28 @@ TEST(SubTree, RecursiveCycle) // clang-format off static const char* xml_text = R"( - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + )"; // clang-format on @@ -789,4 +786,3 @@ TEST(SubTree, RecursiveCycle) ASSERT_ANY_THROW(auto tree = factory.createTreeFromText(xml_text)); } -