https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/195514
>From ebfa459e47829347f3ec926d95e918004d25638a Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Sun, 3 May 2026 11:55:47 +0200 Subject: [PATCH 1/4] [lldb] Trim and show embedded zeros in `char*_t` arrays --- .../lldb/DataFormatters/StringPrinter.h | 7 +++++++ lldb/source/DataFormatters/StringPrinter.cpp | 12 +++++++++++ .../Language/CPlusPlus/CxxStringTypes.cpp | 20 +++++++++++++++++++ .../API/lang/cpp/char1632_t/TestChar1632T.py | 6 ++++++ lldb/test/API/lang/cpp/char1632_t/main.cpp | 8 +++++++- .../API/lang/cpp/char8_t/TestCxxChar8_t.py | 12 +++++++++++ lldb/test/API/lang/cpp/char8_t/main.cpp | 3 +++ .../API/lang/cpp/wchar_t/TestCxxWCharT.py | 3 +++ lldb/test/API/lang/cpp/wchar_t/main.cpp | 9 +++++++-- 9 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lldb/include/lldb/DataFormatters/StringPrinter.h b/lldb/include/lldb/DataFormatters/StringPrinter.h index 4169f53e63f38..0f013564c5999 100644 --- a/lldb/include/lldb/DataFormatters/StringPrinter.h +++ b/lldb/include/lldb/DataFormatters/StringPrinter.h @@ -62,6 +62,10 @@ class StringPrinter { bool GetBinaryZeroIsTerminator() const { return m_zero_is_terminator; } + void SetTrimTrailingZeros(bool v) { m_trim_trailing_zeros = v; } + + bool GetTrimTrailingZeros() const { return m_trim_trailing_zeros; } + void SetEscapeNonPrintables(bool e) { m_escape_non_printables = e; } bool GetEscapeNonPrintables() const { return m_escape_non_printables; } @@ -95,6 +99,9 @@ class StringPrinter { /// True iff a zero bytes ('\0') should terminate the memory region that /// is being dumped. bool m_zero_is_terminator = true; + /// True iff trailing zero bytes should be stripped from the string. + /// Mutually exclusive with `m_zero_is_terminator`. + bool m_trim_trailing_zeros = false; /// The language-specific style for escaping special characters. EscapeStyle m_escape_style = EscapeStyle::CXX; }; diff --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp index 60cb0fc5d6876..a61042b34d29b 100644 --- a/lldb/source/DataFormatters/StringPrinter.cpp +++ b/lldb/source/DataFormatters/StringPrinter.cpp @@ -280,6 +280,11 @@ static bool DumpEncodedBufferToStream( const SourceDataType *data_end_ptr = data_ptr + source_size; const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator(); + const bool trim_trailing_zeros = dump_options.GetTrimTrailingZeros(); + + assert((!zero_is_terminator || !trim_trailing_zeros) && + "BinaryZeroIsTerminator and " + "TrimTrailingZeros are mutually exclusive"); if (zero_is_terminator) { while (data_ptr < data_end_ptr) { @@ -291,6 +296,12 @@ static bool DumpEncodedBufferToStream( } data_ptr = (const SourceDataType *)data.GetDataStart(); + } else if (trim_trailing_zeros) { + while (data_end_ptr != data_ptr) { + if (*(data_end_ptr - 1)) + break; + data_end_ptr--; + } } lldb::WritableDataBufferSP utf8_data_buffer_sp; @@ -385,6 +396,7 @@ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions:: SetQuote(options.GetQuote()); SetEscapeNonPrintables(options.GetEscapeNonPrintables()); SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); + SetTrimTrailingZeros(options.GetTrimTrailingZeros()); SetEscapeStyle(options.GetEscapeStyle()); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index bf8c393445908..f78613861424b 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -60,6 +60,16 @@ static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) { options.SetStream(&stream); options.SetPrefixToken(getElementTraits(ElemType).first); + CompilerType ty = valobj.GetCompilerType(); + uint64_t size = 0; + if (ty.IsArrayType(nullptr, &size) && size > 0) { + options.SetSourceSize(size); + options.SetHasSourceSize(true); + options.SetBinaryZeroIsTerminator(false); + options.SetNeedsZeroTermination(false); + options.SetTrimTrailingZeros(true); + } + if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options)) stream.Printf("Summary Unavailable"); @@ -127,6 +137,16 @@ bool lldb_private::formatters::WCharStringSummaryProvider( options.SetStream(&stream); options.SetPrefixToken("L"); + CompilerType ty = valobj.GetCompilerType(); + uint64_t arr_size = 0; + if (ty.IsArrayType(nullptr, &arr_size) && arr_size > 0) { + options.SetSourceSize(arr_size); + options.SetHasSourceSize(true); + options.SetBinaryZeroIsTerminator(false); + options.SetNeedsZeroTermination(false); + options.SetTrimTrailingZeros(true); + } + switch (wchar_size) { case 1: return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8>( diff --git a/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py b/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py index e2521d88258bc..cd4dc9a406f5c 100644 --- a/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py +++ b/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py @@ -80,6 +80,12 @@ def test(self): substrs=['u"ﺸﺵۻ"', 'U"ЕЙРГЖО"'], ) + # Check that embedded zeros show up in arrays + self.expect_var_path("aZero16", summary='u"I\\0have\\0zeros"') + self.expect_var_path("cZero16", summary='u"I"') + self.expect_var_path("aZero32", summary='U"I\\0have\\0zeros"') + self.expect_var_path("cZero32", summary='U"I"') + self.runCmd("next") # step to after the string is nullified # check that we don't crash on NULL diff --git a/lldb/test/API/lang/cpp/char1632_t/main.cpp b/lldb/test/API/lang/cpp/char1632_t/main.cpp index dc37df27fceb5..e38188cf85dee 100644 --- a/lldb/test/API/lang/cpp/char1632_t/main.cpp +++ b/lldb/test/API/lang/cpp/char1632_t/main.cpp @@ -10,7 +10,7 @@ void copy_char_seq (T (&arr)[N], const T* src) assert(src_len < N); std::char_traits<T>::copy(arr, src, src_len); - arr[src_len] = 0; + memset(&arr[src_len], 0, (N - src_len) * sizeof(T)); } int main (int argc, char const *argv[]) @@ -25,6 +25,12 @@ int main (int argc, char const *argv[]) char32_t *s32 = (char32_t *)U"ЕЙРГЖО"; copy_char_seq(as16, s16); copy_char_seq(as32, s32); + + char16_t aZero16[32] = u"I\0have\0zeros"; + const char16_t *cZero16 = u"I\0have\0zeros"; + char32_t aZero32[32] = U"I\0have\0zeros"; + const char32_t *cZero32 = U"I\0have\0zeros"; + s32 = nullptr; // breakpoint1 s32 = (char32_t *)U"෴"; s16 = (char16_t *)u"色ハ匂ヘト散リヌルヲ"; diff --git a/lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py b/lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py index 08f09b317b217..c727ae9cf6ab6 100644 --- a/lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py +++ b/lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py @@ -21,10 +21,18 @@ def test_without_process(self): self.expect("target variable a", substrs=["char8_t", "0x61 u8'a'"]) self.expect("target variable ab", substrs=["const char8_t *", 'u8"你好"']) self.expect("target variable abc", substrs=["char8_t[9]", 'u8"你好"']) + self.expect( + "target variable aZero", substrs=["char8_t[32]", 'u8"I\\0have\\0zeros"'] + ) + self.expect("target variable cZero", substrs=["const char8_t *", 'u8"I"']) self.expect_expr("a", result_type="char8_t", result_summary="0x61 u8'a'") self.expect_expr("ab", result_type="const char8_t *", result_summary='u8"你好"') self.expect_expr("abc", result_type="char8_t[9]", result_summary='u8"你好"') + self.expect_expr( + "aZero", result_type="char8_t[32]", result_summary='u8"I\\0have\\0zeros"' + ) + self.expect_expr("cZero", result_type="const char8_t *", result_summary='u8"I"') @skipIf(compiler="clang", compiler_version=["<", "7.0"]) def test_with_process(self): @@ -38,3 +46,7 @@ def test_with_process(self): self.expect_expr("a", result_type="char8_t", result_summary="0x61 u8'a'") self.expect_expr("ab", result_type="const char8_t *", result_summary='u8"你好"') self.expect_expr("abc", result_type="char8_t[9]", result_summary='u8"你好"') + self.expect_expr( + "aZero", result_type="char8_t[32]", result_summary='u8"I\\0have\\0zeros"' + ) + self.expect_expr("cZero", result_type="const char8_t *", result_summary='u8"I"') diff --git a/lldb/test/API/lang/cpp/char8_t/main.cpp b/lldb/test/API/lang/cpp/char8_t/main.cpp index d109751cc2314..36a2bbef95e2b 100644 --- a/lldb/test/API/lang/cpp/char8_t/main.cpp +++ b/lldb/test/API/lang/cpp/char8_t/main.cpp @@ -2,6 +2,9 @@ char8_t a = u8'a'; const char8_t* ab = u8"你好"; char8_t abc[9] = u8"你好"; +char8_t aZero[32] = u8"I\0have\0zeros"; +const char8_t *cZero = u8"I\0have\0zeros"; + int main (int argc, char const *argv[]) { return 0; // break here } diff --git a/lldb/test/API/lang/cpp/wchar_t/TestCxxWCharT.py b/lldb/test/API/lang/cpp/wchar_t/TestCxxWCharT.py index 35cb512142ca0..f17d5a707c9e3 100644 --- a/lldb/test/API/lang/cpp/wchar_t/TestCxxWCharT.py +++ b/lldb/test/API/lang/cpp/wchar_t/TestCxxWCharT.py @@ -48,3 +48,6 @@ def test(self): self.expect("frame variable wchar_zero", substrs=["L'\\0'"]) self.expect("expression wchar_zero", substrs=["L'\\0'"]) + + self.expect_var_path("aZero", summary='L"I\\0have\\0zeros"') + self.expect_var_path("cZero", summary='L"I"') diff --git a/lldb/test/API/lang/cpp/wchar_t/main.cpp b/lldb/test/API/lang/cpp/wchar_t/main.cpp index 778642e0133f0..f6031ae9f7b9d 100644 --- a/lldb/test/API/lang/cpp/wchar_t/main.cpp +++ b/lldb/test/API/lang/cpp/wchar_t/main.cpp @@ -19,8 +19,13 @@ int main (int argc, char const *argv[]) const wchar_t *mazeltov = L"מזל טוב"; wchar_t *ws_NULL = nullptr; wchar_t *ws_empty = L""; - wchar_t array[200], * array_source = L"Hey, I'm a super wchar_t string, éõñž"; + wchar_t array[200], + *array_source = L"Hey, I'm a super wchar_t string, éõñž"; wchar_t wchar_zero = (wchar_t)0; - memcpy(array, array_source, 39 * sizeof(wchar_t)); + memcpy(array, array_source, 39 * sizeof(wchar_t)); + + wchar_t aZero[32] = L"I\0have\0zeros"; + const wchar_t *cZero = L"I\0have\0zeros"; + return 0; // break here } >From 036864574f81998e47192f12ef83191a8e72e0a6 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Tue, 5 May 2026 15:09:23 +0200 Subject: [PATCH 2/4] refactor: Use enum for zero-termination --- .../lldb/DataFormatters/StringPrinter.h | 29 +++++++---------- lldb/source/DataFormatters/StringPrinter.cpp | 32 +++++++++++-------- .../Language/CPlusPlus/CxxStringTypes.cpp | 16 ++++------ .../source/Plugins/Language/ObjC/NSString.cpp | 24 ++++++++------ lldb/source/ValueObject/ValueObject.cpp | 8 ++++- .../DataFormatter/StringPrinterTests.cpp | 2 +- 6 files changed, 59 insertions(+), 52 deletions(-) diff --git a/lldb/include/lldb/DataFormatters/StringPrinter.h b/lldb/include/lldb/DataFormatters/StringPrinter.h index 0f013564c5999..caba15273469c 100644 --- a/lldb/include/lldb/DataFormatters/StringPrinter.h +++ b/lldb/include/lldb/DataFormatters/StringPrinter.h @@ -26,6 +26,15 @@ class StringPrinter { enum class EscapeStyle { CXX, Swift }; + enum class ZeroTermination : uint8_t { + /// Don't look for a terminator - print the whole buffer. + Ignore, + /// Stop printing at the first zero terminator. + ZeroTerminate, + /// Print embedded zeros, but ignore zeros at the end of the buffer. + TrimTrailingZeros, + }; + class DumpToStreamOptions { public: DumpToStreamOptions() = default; @@ -54,17 +63,9 @@ class StringPrinter { uint32_t GetSourceSize() const { return m_source_size; } - void SetNeedsZeroTermination(bool z) { m_needs_zero_termination = z; } - - bool GetNeedsZeroTermination() const { return m_needs_zero_termination; } - - void SetBinaryZeroIsTerminator(bool e) { m_zero_is_terminator = e; } - - bool GetBinaryZeroIsTerminator() const { return m_zero_is_terminator; } - - void SetTrimTrailingZeros(bool v) { m_trim_trailing_zeros = v; } + void SetZeroTermination(ZeroTermination z) { m_zero_termination = z; } - bool GetTrimTrailingZeros() const { return m_trim_trailing_zeros; } + ZeroTermination GetZeroTermination() const { return m_zero_termination; } void SetEscapeNonPrintables(bool e) { m_escape_non_printables = e; } @@ -89,21 +90,15 @@ class StringPrinter { char m_quote = '"'; /// The length of the memory region that should be dumped in bytes. uint32_t m_source_size = 0; - bool m_needs_zero_termination = true; /// True iff non-printable characters should be escaped when dumping /// them to the stream. bool m_escape_non_printables = true; /// True iff the max-string-summary-length setting of the target should /// be ignored. bool m_ignore_max_length = false; - /// True iff a zero bytes ('\0') should terminate the memory region that - /// is being dumped. - bool m_zero_is_terminator = true; - /// True iff trailing zero bytes should be stripped from the string. - /// Mutually exclusive with `m_zero_is_terminator`. - bool m_trim_trailing_zeros = false; /// The language-specific style for escaping special characters. EscapeStyle m_escape_style = EscapeStyle::CXX; + ZeroTermination m_zero_termination = ZeroTermination::ZeroTerminate; }; class ReadStringAndDumpToStreamOptions : public DumpToStreamOptions { diff --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp index a61042b34d29b..81b81fffcf73a 100644 --- a/lldb/source/DataFormatters/StringPrinter.cpp +++ b/lldb/source/DataFormatters/StringPrinter.cpp @@ -279,14 +279,11 @@ static bool DumpEncodedBufferToStream( (const SourceDataType *)data.GetDataStart(); const SourceDataType *data_end_ptr = data_ptr + source_size; - const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator(); - const bool trim_trailing_zeros = dump_options.GetTrimTrailingZeros(); + switch (dump_options.GetZeroTermination()) { + case StringPrinter::ZeroTermination::Ignore: + break; - assert((!zero_is_terminator || !trim_trailing_zeros) && - "BinaryZeroIsTerminator and " - "TrimTrailingZeros are mutually exclusive"); - - if (zero_is_terminator) { + case StringPrinter::ZeroTermination::ZeroTerminate: { while (data_ptr < data_end_ptr) { if (!*data_ptr) { data_end_ptr = data_ptr; @@ -296,13 +293,19 @@ static bool DumpEncodedBufferToStream( } data_ptr = (const SourceDataType *)data.GetDataStart(); - } else if (trim_trailing_zeros) { + } break; + + case StringPrinter::ZeroTermination::TrimTrailingZeros: { while (data_end_ptr != data_ptr) { if (*(data_end_ptr - 1)) break; data_end_ptr--; } + } break; } + const bool zero_is_terminator = + dump_options.GetZeroTermination() == + StringPrinter::ZeroTermination::ZeroTerminate; lldb::WritableDataBufferSP utf8_data_buffer_sp; llvm::UTF8 *utf8_data_ptr = nullptr; @@ -395,8 +398,7 @@ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions:: SetSuffixToken(options.GetSuffixToken()); SetQuote(options.GetQuote()); SetEscapeNonPrintables(options.GetEscapeNonPrintables()); - SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); - SetTrimTrailingZeros(options.GetTrimTrailingZeros()); + SetZeroTermination(options.GetZeroTermination()); SetEscapeStyle(options.GetEscapeStyle()); } @@ -431,7 +433,8 @@ static bool ReadEncodedBufferAndDumpToStream( if (origin_encoding != 8 && !ConvertFunction) return false; - bool needs_zero_terminator = options.GetNeedsZeroTermination(); + bool needs_zero_terminator = options.GetZeroTermination() == + StringPrinter::ZeroTermination::ZeroTerminate; bool is_truncated = false; const auto max_size = target_sp->GetMaximumSizeOfStringSummary(); @@ -491,9 +494,10 @@ static bool ReadEncodedBufferAndDumpToStream( target_sp->GetArchitecture().GetAddressByteSize())); dump_options.SetSourceSize(sourceSize); dump_options.SetIsTruncated(is_truncated); - dump_options.SetNeedsZeroTermination(needs_zero_terminator); - if (needs_zero_terminator) - dump_options.SetBinaryZeroIsTerminator(true); + if (needs_zero_terminator) { + dump_options.SetZeroTermination( + StringPrinter::ZeroTermination::ZeroTerminate); + } GetPrintableElementType print_style = (elem_type == StringElementType::ASCII) ? GetPrintableElementType::ASCII diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index f78613861424b..347c108a9a72a 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -65,9 +65,8 @@ static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) { if (ty.IsArrayType(nullptr, &size) && size > 0) { options.SetSourceSize(size); options.SetHasSourceSize(true); - options.SetBinaryZeroIsTerminator(false); - options.SetNeedsZeroTermination(false); - options.SetTrimTrailingZeros(true); + options.SetZeroTermination( + StringPrinter::ZeroTermination::TrimTrailingZeros); } if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options)) @@ -99,7 +98,7 @@ static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) { options.SetPrefixToken(ElemTraits.first); options.SetQuote('\''); options.SetSourceSize(1); - options.SetBinaryZeroIsTerminator(false); + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); return StringPrinter::ReadBufferAndDumpToStream<ElemType>(options); } @@ -142,9 +141,8 @@ bool lldb_private::formatters::WCharStringSummaryProvider( if (ty.IsArrayType(nullptr, &arr_size) && arr_size > 0) { options.SetSourceSize(arr_size); options.SetHasSourceSize(true); - options.SetBinaryZeroIsTerminator(false); - options.SetNeedsZeroTermination(false); - options.SetTrimTrailingZeros(true); + options.SetZeroTermination( + StringPrinter::ZeroTermination::TrimTrailingZeros); } switch (wchar_size) { @@ -200,7 +198,7 @@ bool lldb_private::formatters::WCharSummaryProvider( options.SetPrefixToken("L"); options.SetQuote('\''); options.SetSourceSize(1); - options.SetBinaryZeroIsTerminator(false); + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); switch (wchar_size) { case 1: @@ -267,7 +265,7 @@ bool lldb_private::formatters::StringBufferSummaryProvider( options.SetPrefixToken(prefix_token); options.SetQuote('"'); options.SetSourceSize(size); - options.SetBinaryZeroIsTerminator(false); + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); return StringPrinter::ReadBufferAndDumpToStream<element_type>(options); } diff --git a/lldb/source/Plugins/Language/ObjC/NSString.cpp b/lldb/source/Plugins/Language/ObjC/NSString.cpp index ce268ac7f3257..7a295119bd031 100644 --- a/lldb/source/Plugins/Language/ObjC/NSString.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSString.cpp @@ -151,10 +151,9 @@ bool lldb_private::formatters::NSStringSummaryProvider( options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetHasSourceSize(has_explicit_length); - options.SetNeedsZeroTermination(false); + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - options.SetBinaryZeroIsTerminator(false); return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); } else { @@ -163,10 +162,9 @@ bool lldb_private::formatters::NSStringSummaryProvider( options.SetStream(&stream); options.SetSourceSize(explicit_length); options.SetHasSourceSize(has_explicit_length); - options.SetNeedsZeroTermination(false); + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - options.SetBinaryZeroIsTerminator(false); return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::ASCII>(options); } @@ -202,10 +200,12 @@ bool lldb_private::formatters::NSStringSummaryProvider( options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetHasSourceSize(has_explicit_length); - options.SetNeedsZeroTermination(!has_explicit_length); + if (has_explicit_length) + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); + else + options.SetZeroTermination(StringPrinter::ZeroTermination::ZeroTerminate); options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - options.SetBinaryZeroIsTerminator(!has_explicit_length); return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); } else if (is_path_store) { @@ -228,10 +228,12 @@ bool lldb_private::formatters::NSStringSummaryProvider( options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetHasSourceSize(has_explicit_length); - options.SetNeedsZeroTermination(!has_explicit_length); + if (has_explicit_length) + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); + else + options.SetZeroTermination(StringPrinter::ZeroTermination::ZeroTerminate); options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - options.SetBinaryZeroIsTerminator(!has_explicit_length); return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); } else if (is_inline) { @@ -250,10 +252,12 @@ bool lldb_private::formatters::NSStringSummaryProvider( options.SetStream(&stream); options.SetSourceSize(explicit_length); options.SetHasSourceSize(has_explicit_length); - options.SetNeedsZeroTermination(!has_explicit_length); + if (has_explicit_length) + options.SetZeroTermination(StringPrinter::ZeroTermination::Ignore); + else + options.SetZeroTermination(StringPrinter::ZeroTermination::ZeroTerminate); options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - options.SetBinaryZeroIsTerminator(!has_explicit_length); if (has_explicit_length) return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF8>(options); diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp index 33f143bb4e3e2..9903356cf4726 100644 --- a/lldb/source/ValueObject/ValueObject.cpp +++ b/lldb/source/ValueObject/ValueObject.cpp @@ -1403,7 +1403,13 @@ bool ValueObject::DumpPrintableRepresentation( options.SetQuote('"'); options.SetSourceSize(buffer_sp->GetByteSize()); options.SetIsTruncated(read_string.second); - options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar); + if (custom_format == eFormatVectorOfChar) { + options.SetZeroTermination( + formatters::StringPrinter::ZeroTermination::Ignore); + } else { + options.SetZeroTermination( + formatters::StringPrinter::ZeroTermination::ZeroTerminate); + } formatters::StringPrinter::ReadBufferAndDumpToStream< lldb_private::formatters::StringPrinter::StringElementType::ASCII>( options); diff --git a/lldb/unittests/DataFormatter/StringPrinterTests.cpp b/lldb/unittests/DataFormatter/StringPrinterTests.cpp index ac4116139beb2..64789bccd3e87 100644 --- a/lldb/unittests/DataFormatter/StringPrinterTests.cpp +++ b/lldb/unittests/DataFormatter/StringPrinterTests.cpp @@ -32,7 +32,7 @@ format(StringRef input, StringPrinter::EscapeStyle escape_style) { StringPrinter::ReadBufferAndDumpToStreamOptions opts; opts.SetStream(&out); opts.SetSourceSize(input.size()); - opts.SetNeedsZeroTermination(true); + opts.SetZeroTermination(StringPrinter::ZeroTermination::ZeroTerminate); opts.SetEscapeNonPrintables(true); opts.SetIgnoreMaxLength(false); opts.SetEscapeStyle(escape_style); >From 4f7616ffb9289197f0e5e06aa16a987e9a8c9381 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 6 May 2026 12:59:43 +0200 Subject: [PATCH 3/4] fix: enum size --- lldb/include/lldb/DataFormatters/StringPrinter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/DataFormatters/StringPrinter.h b/lldb/include/lldb/DataFormatters/StringPrinter.h index caba15273469c..0a674b9fb303e 100644 --- a/lldb/include/lldb/DataFormatters/StringPrinter.h +++ b/lldb/include/lldb/DataFormatters/StringPrinter.h @@ -26,7 +26,7 @@ class StringPrinter { enum class EscapeStyle { CXX, Swift }; - enum class ZeroTermination : uint8_t { + enum class ZeroTermination { /// Don't look for a terminator - print the whole buffer. Ignore, /// Stop printing at the first zero terminator. >From 520c4a926c30fd4d899304defd31f5b88a18a439 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 6 May 2026 13:00:53 +0200 Subject: [PATCH 4/4] fix: update comments --- lldb/source/DataFormatters/StringPrinter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp index 81b81fffcf73a..3a6a55e9d4e02 100644 --- a/lldb/source/DataFormatters/StringPrinter.cpp +++ b/lldb/source/DataFormatters/StringPrinter.cpp @@ -442,8 +442,8 @@ static bool ReadEncodedBufferAndDumpToStream( uint32_t sourceSize; if (elem_type == StringElementType::ASCII && !options.GetSourceSize()) { // FIXME: The NSString formatter sets HasSourceSize(true) when the size is - // actually unknown, as well as SetBinaryZeroIsTerminator(false). IIUC the - // C++ formatter also sets SetBinaryZeroIsTerminator(false) when it doesn't + // actually unknown, as well as SetZeroTermination(Ignore). IIUC the + // C++ formatter also sets SetZeroTermination(Ignore) when it doesn't // mean to. I don't see how this makes sense: we should fix the formatters. // // Until then, the behavior that's expected for ASCII strings with unknown _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
