Use the provided length in ConditionalPrintAsText

While ConditionalPrintAsText gets a char pointer and the string length, it used to only pass the pointer to operator<<. That does not work for strings that are not zero terminated, because operator<< has to resort to strlen, which happily overflows the string buffer.

This CL wraps the char pointer and the length in a string_view and passes that to operator<< to fix that issue.

PiperOrigin-RevId: 765137769
Change-Id: Ie97067ce9d5b23175a512945fee943a8b95a94ff
This commit is contained in:
Abseil Team 2025-05-30 04:46:26 -07:00 committed by Copybara-Service
parent 7da55820cc
commit 7427a6b5e3
2 changed files with 17 additions and 1 deletions

View File

@ -516,7 +516,7 @@ bool IsValidUTF8(const char* str, size_t length) {
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
if (!ContainsUnprintableControlCodes(str, length) &&
IsValidUTF8(str, length)) {
*os << "\n As Text: \"" << str << "\"";
*os << "\n As Text: \"" << ::std::string_view(str, length) << "\"";
}
}

View File

@ -1929,6 +1929,22 @@ TEST(UniversalPrintTest, SmartPointers) {
PrintToString(std::shared_ptr<void>(p.get(), [](void*) {})));
}
TEST(UniversalPrintTest, StringViewNonZeroTerminated) {
// Craft a non-ASCII UTF-8 input (to trigger a special path in
// `ConditionalPrintAsText`). Use array notation instead of the string
// literal syntax, to avoid placing a terminating 0 at the end of the input.
const char s[] = {'\357', '\243', '\242', 'X'};
// Only include the first 3 bytes in the `string_view` and leave the last one
// ('X') outside. This way, if the code tries to use `str.data()` with
// `strlen` instead of `str.size()`, it will include 'X' and cause a visible
// difference (in addition to ASAN tests detecting a buffer overflow due to
// the missing 0 at the end).
const ::std::string_view str(s, 3);
::std::stringstream ss;
UniversalPrint(str, &ss);
EXPECT_EQ("\"\\xEF\\xA3\\xA2\"\n As Text: \"\xEF\xA3\xA2\"", ss.str());
}
TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
EXPECT_EQ(0u, result.size());