summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node.gyp1
-rw-r--r--src/node_report_utils.cc53
-rw-r--r--test/cctest/test_report_util.cc26
3 files changed, 60 insertions, 20 deletions
diff --git a/node.gyp b/node.gyp
index 3beeb71c1d..d762b8c301 100644
--- a/node.gyp
+++ b/node.gyp
@@ -980,6 +980,7 @@
'test/cctest/test_node_postmortem_metadata.cc',
'test/cctest/test_environment.cc',
'test/cctest/test_platform.cc',
+ 'test/cctest/test_report_util.cc',
'test/cctest/test_traced_value.cc',
'test/cctest/test_util.cc',
'test/cctest/test_url.cc'
diff --git a/src/node_report_utils.cc b/src/node_report_utils.cc
index 2cd92599b0..75eb33250a 100644
--- a/src/node_report_utils.cc
+++ b/src/node_report_utils.cc
@@ -214,28 +214,41 @@ void WalkHandle(uv_handle_t* h, void* arg) {
writer->json_end();
}
-static std::string findAndReplace(const std::string& str,
- const std::string& old,
- const std::string& neu) {
- std::string ret = str;
+std::string EscapeJsonChars(const std::string& str) {
+ const std::string control_symbols[0x20] = {
+ "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
+ "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r",
+ "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013",
+ "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019",
+ "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"
+ };
+
+ std::string ret = "";
+ size_t last_pos = 0;
size_t pos = 0;
- while ((pos = ret.find(old, pos)) != std::string::npos) {
- ret.replace(pos, old.length(), neu);
- pos += neu.length();
+ for (; pos < str.size(); ++pos) {
+ std::string replace;
+ char ch = str[pos];
+ if (ch == '\\') {
+ replace = "\\\\";
+ } else if (ch == '\"') {
+ replace = "\\\"";
+ } else {
+ size_t num = static_cast<size_t>(ch);
+ if (num < 0x20) replace = control_symbols[num];
+ }
+ if (!replace.empty()) {
+ if (pos > last_pos) {
+ ret += str.substr(last_pos, pos - last_pos);
+ }
+ last_pos = pos + 1;
+ ret += replace;
+ }
+ }
+ // Append any remaining symbols.
+ if (last_pos < str.size()) {
+ ret += str.substr(last_pos, pos - last_pos);
}
- return ret;
-}
-
-std::string EscapeJsonChars(const std::string& str) {
- std::string ret = str;
- ret = findAndReplace(ret, "\\", "\\\\");
- ret = findAndReplace(ret, "\\u", "\\u");
- ret = findAndReplace(ret, "\n", "\\n");
- ret = findAndReplace(ret, "\f", "\\f");
- ret = findAndReplace(ret, "\r", "\\r");
- ret = findAndReplace(ret, "\b", "\\b");
- ret = findAndReplace(ret, "\t", "\\t");
- ret = findAndReplace(ret, "\"", "\\\"");
return ret;
}
diff --git a/test/cctest/test_report_util.cc b/test/cctest/test_report_util.cc
new file mode 100644
index 0000000000..e32558ef75
--- /dev/null
+++ b/test/cctest/test_report_util.cc
@@ -0,0 +1,26 @@
+#include "node_report.h"
+
+#include "gtest/gtest.h"
+
+TEST(ReportUtilTest, EscapeJsonChars) {
+ using report::EscapeJsonChars;
+ EXPECT_EQ("abc", EscapeJsonChars("abc"));
+ EXPECT_EQ("abc\\n", EscapeJsonChars("abc\n"));
+ EXPECT_EQ("abc\\nabc", EscapeJsonChars("abc\nabc"));
+ EXPECT_EQ("abc\\\\", EscapeJsonChars("abc\\"));
+ EXPECT_EQ("abc\\\"", EscapeJsonChars("abc\""));
+
+ const std::string expected[0x20] = {
+ "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
+ "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r",
+ "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013",
+ "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019",
+ "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"
+ };
+ for (int i = 0; i < 0x20; ++i) {
+ char symbols[1] = { static_cast<char>(i) };
+ std::string input(symbols, 1);
+ EXPECT_EQ(expected[i], EscapeJsonChars(input));
+ EXPECT_EQ("a" + expected[i], EscapeJsonChars("a" + input));
+ }
+}