Fix basic_static_cstring::compare(const CharT*) for over-long inputs

compare(const CharT* s) constructed a temporary basic_static_cstring<N>
from s and delegated to the class-type overload. The constructor throws
std::length_error when traits::length(s) > N, and because compare() is
noexcept, the throw led to std::terminate():

  static_cstring<3> s("abc");
  s.compare("abcd");              // terminate() via noexcept throw

The free operator==() / operator!=() overloads for const CharT*, which
delegate to compare(), had the same flaw.
This commit is contained in:
Gennaro Prota
2026-04-21 16:13:29 +02:00
parent c6cd8074ab
commit 62ed5ee17a
2 changed files with 40 additions and 1 deletions
+11 -1
View File
@@ -363,7 +363,17 @@ public:
constexpr int compare(const CharT* s) const noexcept
{
return compare(basic_static_cstring(s));
const size_type lhs_sz = size();
const size_type rhs_sz = traits_type::length(s);
const int result = traits_type::compare(data_, s, (std::min)(lhs_sz, rhs_sz));
return result != 0
? result
: lhs_sz < rhs_sz
? -1
: lhs_sz > rhs_sz
? 1
: 0;
}
// Conversions.
@@ -443,6 +443,35 @@ testCStringComparison()
BOOST_TEST(s.compare("abd") < 0);
BOOST_TEST(s.compare("abb") > 0);
}
// compare(const CharT*) must not throw when the argument is longer
// than the static capacity.
{
static_cstring<3> s("abc");
BOOST_TEST(s.compare("abcd") < 0);
BOOST_TEST(s.compare("abcdefghijklmnop") < 0);
BOOST_TEST(s.compare("abb") > 0);
BOOST_TEST(s.compare("abd") < 0);
BOOST_TEST(s.compare("abc") == 0);
BOOST_TEST(s.compare("ab") > 0);
BOOST_TEST(s.compare("") > 0);
}
// Same via operator== / operator!= with an over-long C string.
{
static_cstring<3> s("abc");
BOOST_TEST(!(s == "abcd"));
BOOST_TEST(s != "abcd");
BOOST_TEST(!("abcd" == s));
BOOST_TEST("abcd" != s);
}
// Empty static_cstring vs non-empty C string.
{
static_cstring<5> empty;
BOOST_TEST(empty.compare("hello") < 0);
BOOST_TEST(empty.compare("") == 0);
}
}
static