Fix control characters in JSON. submit/tizen/20211019.042902
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Mon, 18 Oct 2021 16:18:31 +0000 (09:18 -0700)
committer이형주/Common Platform Lab(SR)/Principal Engineer/삼성전자 <leee.lee@samsung.com>
Tue, 19 Oct 2021 00:52:19 +0000 (09:52 +0900)
Based on https://github.com/Samsung/netcoredbg/pull/60.

src/protocols/miprotocol.cpp
src/protocols/vscodeprotocol.cpp
src/unittests/escaped_string_test.cpp
src/utils/escaped_string.cpp
src/utils/escaped_string.h
src/utils/span.h

index fffb6818e0ad499a82769fe1e7ab40d37156cfc8..4dbd76ad9f850d4b24fda5fcebeaef60cc330330 100644 (file)
@@ -1253,14 +1253,14 @@ struct MIProtocol::MIProtocolChars
     static const char forbidden_chars[];
 
     // substitutions (except of '\\' prefix)
-    static const char subst_chars[];
+    static const string_view subst_chars[];
 
     static constexpr const char escape_char = '\\';
 };
 
 
 const char MIProtocol::MIProtocolChars::forbidden_chars[] = "\"\\\0\a\b\f\n\r\t\v";
-const char MIProtocol::MIProtocolChars::subst_chars[] = "\"\\0abfnrtv";
+const string_view MIProtocol::MIProtocolChars::subst_chars[] = { "\\\"", "\\\\", "\\0", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v" };
 const char MIProtocol::MIProtocolChars::escape_char;
 
 
index ea7e8278a3c0e61c1ef0ed9076aa41edead24c3f..7460e1385570b405fb84802044921240cc05e2b0 100644 (file)
@@ -259,13 +259,23 @@ namespace
     struct JSON_escape_rules
     {
        static const char forbidden_chars[];
-       static const char subst_chars[];
+       static const string_view subst_chars[];
        constexpr static const char escape_char = '\\';
     };
 
     // Allocate static memory for strings declared above.
-    const char JSON_escape_rules::forbidden_chars[] = "\b\f\n\r\t\"\\";
-    const char JSON_escape_rules::subst_chars[] = "bfnrt\"\\";
+    const char JSON_escape_rules::forbidden_chars[] =
+    "\"\\"
+    "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
+    "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037";
+
+    const string_view JSON_escape_rules::subst_chars[] = {
+        "\\\"", "\\\\",
+        "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007",
+        "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f",
+        "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
+        "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"
+    };
 
     // This function serializes "OutputEvent" to specified output stream and used for two
     // purposes: to compute output size, and to perform the output directly.
index e0da2d60784cc9b67cba7e8f7de55977389011f0..f5672f5f8caf68b7ff7dd5d9dad059524a71687a 100644 (file)
@@ -13,12 +13,14 @@ using string_view = Utility::string_view;
 struct EscapeRules
 {
     static const char forbidden_chars[];
-    static const char subst_chars[];
+    static const string_view subst_chars[];
     static const char constexpr escape_char = '\\';
 };
 
 const char EscapeRules::forbidden_chars[] = "\"\\\0\a\b\f\n\r\t\v";
-const char EscapeRules::subst_chars[] = "\"\\0abfnrtv";
+const string_view EscapeRules::subst_chars[] {
+    "\\\"", "\\\\", "\\0", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v"
+};
 
 using ES = EscapedString<EscapeRules>;
 
index 3a247ca8ba3219af01bddb4dccdebfd1c0f2184a..523e3c76314d6291fe0700ba46d4139781ed92a2 100644 (file)
@@ -47,10 +47,10 @@ void EscapedStringInternal::EscapedStringImpl::operator()(void *thiz, void (*fun
         {
             // find right substitution for forbidden character and output substituting pair of characters
             auto ir = std::find(m_params.forbidden.begin(), m_params.forbidden.end(), *it);
-            char s[2] = {m_params.escape, m_params.subst[ir - m_params.forbidden.begin()]};
-            func(thiz, {s, 2});
-            size += 2;
-            prefix_size += 1;
+            string_view subst = m_params.subst[ir - m_params.forbidden.begin()];
+            func(thiz, subst);
+            size += subst.size();
+            prefix_size++;
         }
 
         src.remove_prefix(prefix_size);
index 2ed148c09b6f7489f3fcfa4f28aeb8803b598ee9..e8f84669e06eb7dc5cf4866b26870cd7b67ed2eb 100644 (file)
@@ -4,6 +4,8 @@
 #pragma once
 #include <utility>
 #include <string>
+#include "utility.h"
+#include "utils/span.h"
 #include "utils/string_view.h"
 
 namespace netcoredbg
@@ -63,9 +65,9 @@ namespace EscapedStringInternal
         // it's template parameters should be stored in `Params` class.
         struct Params
         {
-            string_view forbidden;  // characters which must be replaced
-            string_view subst;      // characters to which `forbidden` characters must be replaced
-            char        escape;     // character, which preceedes each substitution
+            string_view forbidden;                  // characters which must be replaced
+            Utility::span<const string_view> subst; // strings to which `forbidden` characters must be replaced
+            char escape;                            // character, which preceedes each substitution
         };
 
         using TempRef = TempReference<EscapedStringImpl>;
@@ -183,10 +185,10 @@ private:
 // instantiation of Params structure for particular Traits template parameter
 template <typename Traits> EscapedStringInternal::EscapedStringImpl::Params EscapedString<Traits>::params =
 {
-    { ((void)([]() -> void {static_assert(sizeof(Traits::forbidden_chars) == sizeof(Traits::subst_chars),
+    { ((void)([]() -> void {static_assert(sizeof(Traits::forbidden_chars)-1 == Utility::Size(Traits::subst_chars),
         "forbidden_chars and subst_chars must have same size!");}),
       string_view(Traits::forbidden_chars)) },
-    { string_view(Traits::subst_chars) },
+    { Traits::subst_chars },
     Traits::escape_char
 };
 
index fb569f44273bc951c7bf57e891cd7e93b05f4f33..556e101018f48c29bd67209337f73d12ff0a5642 100644 (file)
@@ -46,6 +46,10 @@ public:
     /// the resulting span has data() == ptr and size() == count.
     span(T* first, size_t count) noexcept : _first(first), _beyond_last(first + count) {}
 
+    /// Constructs a span from array.
+    template <size_t N>
+    span(element_type (&arr)[N]) noexcept : _first(arr), _beyond_last(&arr[N]) {}
+
     /// @{ Construct span which holds references on container elements.
     // TODO add enable_if and check container properties
     template <class Container, typename = typename is_container<Container>::type>