Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Successful run of analyzer integration tests on x86_64-pc-linux-gnu. Pushed to trunk as r14-6634-g30d9a3a69841b1.
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 <dmalc...@redhat.com> --- gcc/json.cc | 94 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/gcc/json.cc b/gcc/json.cc index 90ddd7ab3b15..350917af5df1 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. */ -- 2.26.3