]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
diagnostics: Remove null-termination requirement for json::string
authorLewis Hyatt <lhyatt@gmail.com>
Fri, 4 Nov 2022 16:50:06 +0000 (12:50 -0400)
committerLewis Hyatt <lhyatt@gmail.com>
Tue, 15 Nov 2022 15:50:23 +0000 (10:50 -0500)
json::string currently handles null-terminated data and so can't work with
data that may contain embedded null bytes or that is not null-terminated.
Supporting such data will make json::string more robust in some contexts, such
as SARIF output, which uses it to output user source code that may contain
embedded null bytes.

gcc/ChangeLog:

* json.h (class string): Add M_LEN member to store the length of
the data.  Add constructor taking an explicit length.
* json.cc (string::string):  Implement the new constructor.
(string::print): Support printing strings that are not
null-terminated.  Escape embdedded null bytes on output.
(test_writing_strings): Test the new null-byte-related features of
json::string.

gcc/json.cc
gcc/json.h

index 974f8c368252fb75e697dff4d2fa107b750faf6e..3a79cac02ac575ccdeb6c2af715daca9f6c07225 100644 (file)
@@ -190,6 +190,15 @@ string::string (const char *utf8)
 {
   gcc_assert (utf8);
   m_utf8 = xstrdup (utf8);
+  m_len = strlen (utf8);
+}
+
+string::string (const char *utf8, size_t len)
+{
+  gcc_assert (utf8);
+  m_utf8 = XNEWVEC (char, len);
+  m_len = len;
+  memcpy (m_utf8, utf8, len);
 }
 
 /* Implementation of json::value::print for json::string.  */
@@ -198,9 +207,9 @@ void
 string::print (pretty_printer *pp) const
 {
   pp_character (pp, '"');
-  for (const char *ptr = m_utf8; *ptr; ptr++)
+  for (size_t i = 0; i != m_len; ++i)
     {
-      char ch = *ptr;
+      char ch = m_utf8[i];
       switch (ch)
        {
        case '"':
@@ -224,7 +233,9 @@ string::print (pretty_printer *pp) const
        case '\t':
          pp_string (pp, "\\t");
          break;
-
+       case '\0':
+         pp_string (pp, "\\0");
+         break;
        default:
          pp_character (pp, ch);
        }
@@ -341,6 +352,12 @@ test_writing_strings ()
 
   string contains_quotes ("before \"quoted\" after");
   assert_print_eq (contains_quotes, "\"before \\\"quoted\\\" after\"");
+
+  const char data[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
+  string not_terminated (data, 3);
+  assert_print_eq (not_terminated, "\"abc\"");
+  string embedded_null (data, sizeof data);
+  assert_print_eq (embedded_null, "\"abcd\\0ef\"");
 }
 
 /* Verify that JSON literals are written correctly.  */
index f272981259b80a6e65d99fe43309cec7b26e30a0..f7afd843dc5405d767c8ebe38b8dd0306014d8db 100644 (file)
@@ -156,16 +156,19 @@ class integer_number : public value
 class string : public value
 {
  public:
-  string (const char *utf8);
+  explicit string (const char *utf8);
+  string (const char *utf8, size_t len);
   ~string () { free (m_utf8); }
 
   enum kind get_kind () const final override { return JSON_STRING; }
   void print (pretty_printer *pp) const final override;
 
   const char *get_string () const { return m_utf8; }
+  size_t get_length () const { return m_len; }
 
  private:
   char *m_utf8;
+  size_t m_len;
 };
 
 /* Subclass of value for the three JSON literals "true", "false",