diff --git a/src/threading/formatters/JSON.cc b/src/threading/formatters/JSON.cc index 38b8dcc4c6..1ce8f679ba 100644 --- a/src/threading/formatters/JSON.cc +++ b/src/threading/formatters/JSON.cc @@ -35,7 +35,10 @@ bool JSON::Describe(ODesc* desc, int num_fields, const Field* const* fields, Val } writer.EndObject(); - desc->Add(buffer.GetString()); + + std::string json{buffer.GetString()}; + Finalize(json); + desc->Add(std::move(json)); return true; } @@ -57,10 +60,25 @@ bool JSON::Describe(ODesc* desc, Value* val, const std::string& name) const { BuildJSON(writer, val, name); writer.EndObject(); - desc->Add(buffer.GetString()); + std::string json{buffer.GetString()}; + Finalize(json); + desc->Add(std::move(json)); + return true; } +void JSON::Finalize(std::string& json) const { + // Replace all occurrences of the "\x" marker we may have inserted during + // escaping of the JSON input string with the backslash unicode codepoint. + static std::string pattern{"[zeek\\\\u005C]"}; + size_t pos = 0; + + while ( (pos = json.find(pattern, pos)) != std::string::npos ) { + json.replace(pos, pattern.length(), "\\u005C"); + pos += pattern.length(); + } +} + Value* JSON::ParseValue(const std::string& s, const std::string& name, TypeTag type, TypeTag subtype) const { GetThread()->Error("JSON formatter does not support parsing yet."); return nullptr; diff --git a/src/threading/formatters/JSON.h b/src/threading/formatters/JSON.h index fca567dcdf..8b274eb8c9 100644 --- a/src/threading/formatters/JSON.h +++ b/src/threading/formatters/JSON.h @@ -36,6 +36,7 @@ public: private: void BuildJSON(zeek::json::detail::NullDoubleWriter& writer, Value* val, const std::string& name = "") const; + void Finalize(std::string& json) const; TimeFormat timestamps; bool include_unset_fields; diff --git a/src/util.cc b/src/util.cc index 02e17c74f8..84a20afe3f 100644 --- a/src/util.cc +++ b/src/util.cc @@ -2242,8 +2242,9 @@ void zeek_strerror_r(int zeek_errno, char* buf, size_t buflen) { static string json_escape_byte(char c) { char hex[2] = {'0', '0'}; bytetohex(c, hex); - - string result = "\\x"; + // Hack: put in place a "marker" that survives JSON-encoding, + // that we can then substitute in the resulting JSON. + string result = "[zeek\\u005C]x"; result.append(hex, 2); return result;