Skip to content

Commit a49a047

Browse files
reject trailing characters in SwitchNode numeric comparison (#1178)
1 parent bce9241 commit a49a047

2 files changed

Lines changed: 41 additions & 9 deletions

File tree

src/controls/switch_node.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ bool CheckStringEquality(const std::string& v1, const std::string& v2,
3939
}
4040
}
4141
#if __cpp_lib_to_chars >= 201611L
42-
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
43-
return (ec == std::errc());
42+
const char* end = str.data() + str.size();
43+
auto [ptr, ec] = std::from_chars(str.data(), end, result);
44+
return ec == std::errc() && ptr == end;
4445
#else
4546
try
4647
{
47-
result = std::stoi(str);
48-
return true;
48+
std::size_t pos = 0;
49+
result = std::stoi(str, &pos);
50+
return pos == str.size();
4951
}
5052
catch(...)
5153
{
@@ -60,15 +62,26 @@ bool CheckStringEquality(const std::string& v1, const std::string& v2,
6062
return true;
6163
}
6264
// compare as real numbers next
63-
auto ToReal = [](const std::string& str, auto& result) -> bool {
65+
auto ToReal = [enums](const std::string& str, auto& result) -> bool {
66+
if(enums)
67+
{
68+
auto it = enums->find(str);
69+
if(it != enums->end())
70+
{
71+
result = it->second;
72+
return true;
73+
}
74+
}
6475
#if __cpp_lib_to_chars >= 201611L
65-
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
66-
return (ec == std::errc());
76+
const char* end = str.data() + str.size();
77+
auto [ptr, ec] = std::from_chars(str.data(), end, result);
78+
return ec == std::errc() && ptr == end;
6779
#else
6880
try
6981
{
70-
result = std::stod(str);
71-
return true;
82+
std::size_t pos = 0;
83+
result = std::stod(str, &pos);
84+
return pos == str.size();
7285
}
7386
catch(...)
7487
{

tests/gtest_switch.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "behaviortree_cpp/behavior_tree.h"
55
#include "behaviortree_cpp/bt_factory.h"
6+
#include "behaviortree_cpp/controls/switch_node.h"
67
#include "behaviortree_cpp/tree_node.h"
78

89
#include <gtest/gtest.h>
@@ -245,3 +246,21 @@ TEST_F(SwitchTest, ActionFailure)
245246
ASSERT_EQ(NodeStatus::IDLE, action_42.status());
246247
ASSERT_EQ(NodeStatus::IDLE, action_def.status());
247248
}
249+
250+
TEST(SwitchStringEquality, RejectsTrailingCharacters)
251+
{
252+
using BT::details::CheckStringEquality;
253+
254+
// legitimate matches must keep working
255+
EXPECT_TRUE(CheckStringEquality("5", "5", nullptr));
256+
EXPECT_TRUE(CheckStringEquality("5", "5.0", nullptr));
257+
EXPECT_TRUE(CheckStringEquality("42", "42", nullptr));
258+
EXPECT_TRUE(CheckStringEquality("-7", "-7", nullptr));
259+
260+
// a selector with trailing bytes must not match a numeric case
261+
EXPECT_FALSE(CheckStringEquality("5abc", "5", nullptr));
262+
EXPECT_FALSE(CheckStringEquality("42xxxx", "42", nullptr));
263+
EXPECT_FALSE(CheckStringEquality("1.0junk", "1.0", nullptr));
264+
EXPECT_FALSE(CheckStringEquality("5 ", "5", nullptr));
265+
EXPECT_FALSE(CheckStringEquality("none", "1", nullptr));
266+
}

0 commit comments

Comments
 (0)