diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-12-16 16:16:33 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-12-16 16:16:33 -0500 |
commit | 30d9a3a69841b13ac01397cf879a043c39409572 (patch) | |
tree | 6d57dcd78003d67a5beb0ab5a2a495cf07925d32 | |
parent | 308e9d693cb8499f46357ca882414b85f2ba6a1e (diff) | |
download | gcc-30d9a3a69841b13ac01397cf879a043c39409572.zip gcc-30d9a3a69841b13ac01397cf879a043c39409572.tar.gz gcc-30d9a3a69841b13ac01397cf879a043c39409572.tar.bz2 |
json: fix escaping of object keys
gcc/ChangeLog:
* json.cc (print_escaped_json_string): New, taken from
string::print.
(object::print): Use it for printing keys.
(string::print): Move implementation to
print_escaped_json_string.
(selftest::test_writing_objects): Add a key containing
quote, backslash, and control characters.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
-rw-r--r-- | gcc/json.cc | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/gcc/json.cc b/gcc/json.cc index 90ddd7a..350917a 100644 --- a/gcc/json.cc +++ b/gcc/json.cc @@ -28,6 +28,52 @@ along with GCC; see the file COPYING3. If not see using namespace json; +/* Print a JSON string to PP, escaping '"', control characters, + and embedded null bytes. + The string is required to be UTF-8 encoded. */ + +static void +print_escaped_json_string (pretty_printer *pp, + const char *utf8_str, + size_t len) +{ + pp_character (pp, '"'); + for (size_t i = 0; i != len; ++i) + { + char ch = utf8_str[i]; + switch (ch) + { + case '"': + pp_string (pp, "\\\""); + break; + case '\\': + pp_string (pp, "\\\\"); + break; + case '\b': + pp_string (pp, "\\b"); + break; + case '\f': + pp_string (pp, "\\f"); + break; + case '\n': + pp_string (pp, "\\n"); + break; + case '\r': + pp_string (pp, "\\r"); + break; + case '\t': + pp_string (pp, "\\t"); + break; + case '\0': + pp_string (pp, "\\0"); + break; + default: + pp_character (pp, ch); + } + } + pp_character (pp, '"'); +} + /* class json::value. */ /* Dump this json::value tree to OUTF. @@ -85,9 +131,7 @@ object::print (pretty_printer *pp, bool formatted) const } map_t &mut_map = const_cast<map_t &> (m_map); value *value = *mut_map.get (key); - pp_doublequote (pp); - pp_string (pp, key); // FIXME: escaping? - pp_doublequote (pp); + print_escaped_json_string (pp, key, strlen (key)); pp_string (pp, ": "); const int indent = strlen (key) + 4; if (formatted) @@ -284,41 +328,7 @@ void string::print (pretty_printer *pp, bool formatted ATTRIBUTE_UNUSED) const { - pp_character (pp, '"'); - for (size_t i = 0; i != m_len; ++i) - { - char ch = m_utf8[i]; - switch (ch) - { - case '"': - pp_string (pp, "\\\""); - break; - case '\\': - pp_string (pp, "\\\\"); - break; - case '\b': - pp_string (pp, "\\b"); - break; - case '\f': - pp_string (pp, "\\f"); - break; - case '\n': - pp_string (pp, "\\n"); - break; - case '\r': - pp_string (pp, "\\r"); - break; - case '\t': - pp_string (pp, "\\t"); - break; - case '\0': - pp_string (pp, "\\0"); - break; - default: - pp_character (pp, ch); - } - } - pp_character (pp, '"'); + print_escaped_json_string (pp, m_utf8, m_len); } /* class json::literal, a subclass of json::value. */ @@ -388,13 +398,17 @@ test_writing_objects () object obj; obj.set_string ("foo", "bar"); obj.set_string ("baz", "quux"); + obj.set_string ("\"\\\b\f\n\r\t", "value for awkward key"); + /* This test relies on json::object writing out key/value pairs in key-insertion order. */ ASSERT_PRINT_EQ (obj, true, "{\"foo\": \"bar\",\n" - " \"baz\": \"quux\"}"); + " \"baz\": \"quux\",\n" + " \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}"); ASSERT_PRINT_EQ (obj, false, - "{\"foo\": \"bar\", \"baz\": \"quux\"}"); + "{\"foo\": \"bar\", \"baz\": \"quux\"" + ", \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}"); } /* Verify that JSON arrays are written correctly. */ |