Skip to content

Commit 6bf9c7a

Browse files
committed
Reject port names containing whitespace
1 parent 4ede94d commit 6bf9c7a

4 files changed

Lines changed: 50 additions & 2 deletions

File tree

include/behaviortree_cpp/basic_types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff 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

src/basic_types.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
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

src/xml_parsing.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff 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);

tests/gtest_ports.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff 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\tname"));
869+
EXPECT_FALSE(IsAllowedPortName(" leading"));
870+
EXPECT_FALSE(IsAllowedPortName("trailing "));
871+
EXPECT_FALSE(IsAllowedPortName("has\nnewline"));
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+
}

0 commit comments

Comments
 (0)