diff --git a/include/behaviortree_cpp/utils/simple_string.hpp b/include/behaviortree_cpp/utils/simple_string.hpp index 809860eaa..0a4b438a8 100644 --- a/include/behaviortree_cpp/utils/simple_string.hpp +++ b/include/behaviortree_cpp/utils/simple_string.hpp @@ -110,13 +110,16 @@ class SimpleString bool operator==(const SimpleString& other) const { const size_t N = size(); - return other.size() == N && std::strncmp(data(), other.data(), N) == 0; + // memcmp, not strncmp: the content may hold embedded NUL bytes, and strncmp + // stops at the first one, reporting two different strings of equal length as + // equal. It is also what operator< below compares with. + return other.size() == N && std::memcmp(data(), other.data(), N) == 0; } bool operator!=(const SimpleString& other) const { const size_t N = size(); - return other.size() != N || std::strncmp(data(), other.data(), N) != 0; + return other.size() != N || std::memcmp(data(), other.data(), N) != 0; } bool operator<=(const SimpleString& other) const diff --git a/tests/gtest_simple_string.cpp b/tests/gtest_simple_string.cpp index 579951d97..fc103e529 100644 --- a/tests/gtest_simple_string.cpp +++ b/tests/gtest_simple_string.cpp @@ -377,6 +377,31 @@ TEST(SimpleStringTest, EmptyStringComparison) EXPECT_TRUE(nonEmpty >= empty1); } +// Test comparison of strings that hold embedded NUL bytes +TEST(SimpleStringTest, ComparisonWithEmbeddedNull) +{ + const SimpleString s1(std::string("a\0b", 3)); + const SimpleString s2(std::string("a\0c", 3)); + const SimpleString s3(std::string("a\0b", 3)); + + EXPECT_FALSE(s1 == s2); + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s1 > s2); + + EXPECT_TRUE(s1 == s3); + EXPECT_FALSE(s1 != s3); + + // same thing with the heap representation + const SimpleString l1(std::string("0123456789abcdef\0b", 18)); + const SimpleString l2(std::string("0123456789abcdef\0c", 18)); + + EXPECT_FALSE(l1.isSOO()); + EXPECT_FALSE(l1 == l2); + EXPECT_TRUE(l1 != l2); + EXPECT_TRUE(l1 < l2); +} + // Test that SimpleString size is as expected (16 bytes) TEST(SimpleStringTest, SizeOfSimpleString) {