From 901a1c3601ae946ac7beaaa37b92b0bd51ccf5b9 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:23:49 +0000 Subject: [PATCH] Fix DEL character (0x7F) not being escaped in string literals (#8080) * Initial plan * Fix DEL character encoding in string literals Change condition from `ch >= 128` to `ch >= 127` to include the DEL character (U+007F, 127) in escaped output. This ensures that the non-printable DEL control character is properly escaped as \u{7f} instead of being printed directly. Also add test cases for DEL and other control characters. Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> --- src/test/zstring.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/util/zstring.cpp | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/test/zstring.cpp b/src/test/zstring.cpp index bd79d873f..e77aac15c 100644 --- a/src/test/zstring.cpp +++ b/src/test/zstring.cpp @@ -21,6 +21,42 @@ static void tst_ascii_roundtrip() { } } +// Test that control characters are properly escaped. +static void tst_control_chars_escaped() { + // Test DEL character (0x7F / 127) + zstring del_char(0x7Fu); + std::string del_encoded = del_char.encode(); + bool del_ok = del_encoded == "\\u{7f}"; + + if (!del_ok) { + std::cout << "Failed to escape DEL character (0x7F): got '" << del_encoded + << "', expected '\\u{7f}'\n" << std::flush; + ENSURE(del_ok); + } + + // Test a few other control characters below 0x20 + zstring null_char(0x00u); + std::string null_encoded = null_char.encode(); + bool null_ok = null_encoded == "\\u{0}"; + + if (!null_ok) { + std::cout << "Failed to escape NULL character (0x00): got '" << null_encoded + << "', expected '\\u{0}'\n" << std::flush; + ENSURE(null_ok); + } + + zstring tab_char(0x09u); + std::string tab_encoded = tab_char.encode(); + bool tab_ok = tab_encoded == "\\u{9}"; + + if (!tab_ok) { + std::cout << "Failed to escape TAB character (0x09): got '" << tab_encoded + << "', expected '\\u{9}'\n" << std::flush; + ENSURE(tab_ok); + } +} + void tst_zstring() { tst_ascii_roundtrip(); + tst_control_chars_escaped(); } diff --git a/src/util/zstring.cpp b/src/util/zstring.cpp index 8e08820f6..f60b8d946 100644 --- a/src/util/zstring.cpp +++ b/src/util/zstring.cpp @@ -150,7 +150,7 @@ std::string zstring::encode() const { #define _flush() if (offset > 0) { buffer[offset] = 0; strm << buffer; offset = 0; } for (unsigned i = 0; i < m_buffer.size(); ++i) { unsigned ch = m_buffer[i]; - if (ch < 32 || ch >= 128 || ('\\' == ch && i + 1 < m_buffer.size() && 'u' == m_buffer[i+1])) { + if (ch < 32 || ch >= 127 || ('\\' == ch && i + 1 < m_buffer.size() && 'u' == m_buffer[i+1])) { _flush(); strm << "\\u{" << std::hex << ch << std::dec << '}'; }