From d2937ff4e1a12d667f387ed192af7fee079a5438 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Tue, 10 Oct 2023 09:03:33 +0100 Subject: [PATCH] Escape control characters in keys Previously a key like: "a\u0000\u0001b" = 1 Would get written with literal control characters, rather than escapes: "a<00><01>b" = 1 The "valid/key/quoted-unicode" test from toml-test would fail with this, although it seems they're not run automatically(?) Can also reproduce with something like: % cat test.cpp #include #include int main() { const auto data = toml::parse("test.toml"); std::cout << data << "\n"; return 0; } % cat test.toml "a\u0000\u0001b" = "a\u0000\u0001b" % c++ -I. test.cpp % ./a.out "ab" = "a\u0000\u0001b" % ./a.out | hexdump -C 00000000 22 61 00 01 62 22 20 3d 20 22 61 5c 75 30 30 30 |"a..b" = "a\u000| 00000010 30 5c 75 30 30 30 31 62 22 0a 0a |0\u0001b"..| --- toml/serializer.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/toml/serializer.hpp b/toml/serializer.hpp index 592c33f..23fb89a 100644 --- a/toml/serializer.hpp +++ b/toml/serializer.hpp @@ -63,7 +63,19 @@ format_key(const std::basic_string& k) case '\f': {serialized += "\\f"; break;} case '\n': {serialized += "\\n"; break;} case '\r': {serialized += "\\r"; break;} - default : {serialized += c; break;} + default: { + if (c >= 0x00 && c < 0x20) + { + std::array buf; + std::snprintf(buf.data(), buf.size(), "\\u00%02x", static_cast(c)); + serialized += buf.data(); + } + else + { + serialized += c; + } + break; + } } } serialized += "\"";