File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -443,8 +443,9 @@ template <typename T = AnyTypeAllowed>
443443 auto sname = static_cast <std::string>(name);
444444 if (!IsAllowedPortName (sname))
445445 {
446- throw RuntimeError (" The name of a port must not be `name` or `ID` "
447- " and must start with an alphabetic character. "
446+ throw RuntimeError (" The name of a port must not be `name` or `ID`, "
447+ " must start with an alphabetic character, "
448+ " and must not contain whitespace. "
448449 " Underscore is reserved." );
449450 }
450451
Original file line number Diff line number Diff line change 22#include " behaviortree_cpp/tree_node.h"
33#include " behaviortree_cpp/json_export.h"
44
5+ #include < algorithm>
6+ #include < cctype>
57#include < cstdlib>
68#include < cstring>
79#include < clocale>
@@ -443,6 +445,11 @@ bool IsAllowedPortName(StringView str)
443445 {
444446 return false ;
445447 }
448+ if (std::any_of (str.begin (), str.end (),
449+ [](unsigned char c) { return std::isspace (c); }))
450+ {
451+ return false ;
452+ }
446453 return !IsReservedAttribute (str);
447454}
448455
Original file line number Diff line number Diff line change @@ -214,6 +214,14 @@ void BT::XMLParser::PImpl::loadSubtreeModel(const XMLElement* xml_root)
214214 {
215215 throw RuntimeError (" Missing attribute [name] in port (SubTree model)" );
216216 }
217+ if (!IsAllowedPortName (name))
218+ {
219+ throw RuntimeError (StrCat (" The port name [" , name,
220+ " ] in SubTree [" , subtree_id,
221+ " ] is not valid. Port names must start "
222+ " with an alphabetic character and must "
223+ " not contain whitespace." ));
224+ }
217225 if (auto default_value = port_node->Attribute (" default" ))
218226 {
219227 port.setDefaultValue (default_value);
Original file line number Diff line number Diff line change @@ -861,3 +861,35 @@ TEST(PortTest, VectorAny)
861861 ASSERT_NO_THROW (status = tree.tickOnce ());
862862 ASSERT_EQ (status, NodeStatus::FAILURE);
863863}
864+
865+ TEST (PortTest, IsAllowedPortNameRejectsWhitespace)
866+ {
867+ EXPECT_FALSE (IsAllowedPortName (" my port" ));
868+ EXPECT_FALSE (IsAllowedPortName (" port\t name" ));
869+ EXPECT_FALSE (IsAllowedPortName (" leading" ));
870+ EXPECT_FALSE (IsAllowedPortName (" trailing " ));
871+ EXPECT_FALSE (IsAllowedPortName (" has\n newline" ));
872+
873+ // Sanity check: valid names still work.
874+ EXPECT_TRUE (IsAllowedPortName (" valid_port" ));
875+ EXPECT_TRUE (IsAllowedPortName (" anotherPort123" ));
876+ }
877+
878+ TEST (PortTest, WhitespacePortNameInSubtreeModelThrows)
879+ {
880+ BT::BehaviorTreeFactory factory;
881+
882+ const std::string xml_txt = R"(
883+ <root BTCPP_format="4">
884+ <BehaviorTree ID="MainTree">
885+ <SubTree ID="MySub" my_port="hello" />
886+ </BehaviorTree>
887+ <TreeNodesModel>
888+ <SubTree ID="MySub">
889+ <input_port name="my port" />
890+ </SubTree>
891+ </TreeNodesModel>
892+ </root>)" ;
893+
894+ EXPECT_THROW (factory.createTreeFromText (xml_txt), BT::RuntimeError);
895+ }
You can’t perform that action at this time.
0 commit comments