From 7427a6b5e3e04f895ecad5c647c94629fb2acdc0 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 30 May 2025 04:46:26 -0700 Subject: [PATCH] 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 --- googletest/src/gtest-printers.cc | 2 +- googletest/test/googletest-printers-test.cc | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc index b5d8df6d8..f65573077 100644 --- a/googletest/src/gtest-printers.cc +++ b/googletest/src/gtest-printers.cc @@ -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) << "\""; } } diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc index 6c1a48beb..c5d9756d5 100644 --- a/googletest/test/googletest-printers-test.cc +++ b/googletest/test/googletest-printers-test.cc @@ -1929,6 +1929,22 @@ TEST(UniversalPrintTest, SmartPointers) { PrintToString(std::shared_ptr(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());