[Pkg-bitcoin-commits] [libunivalue] 60/76: Escape all control characters

Jonas Smedegaard dr at jones.dk
Mon Apr 4 09:18:33 UTC 2016


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository libunivalue.

commit 33391915429e51477e4ca6e6601b8a539ad96481
Author: Wladimir J. van der Laan <laanwj at gmail.com>
Date:   Thu Nov 5 21:39:51 2015 +0100

    Escape all control characters
    
    All control characters (U+0000..U+001f) should be escaped according to
    RFC4627.
    
    Also escape `U+007f DELETE` - is not mentioned in RFC4627 as a control
    character, but it is helpful to escape it as many fonts don't render it,
    or weirdly.
---
 gen/gen.cpp            | 14 ++++++++++---
 lib/univalue_escapes.h | 56 +++++++++++++++++++++++++-------------------------
 lib/univalue_write.cpp |  4 ++--
 test/round1.json       |  1 +
 test/unitester.cpp     | 15 +++++++++++++-
 5 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/gen/gen.cpp b/gen/gen.cpp
index 5e5a4d4..4d24bbe 100644
--- a/gen/gen.cpp
+++ b/gen/gen.cpp
@@ -16,10 +16,17 @@
 using namespace std;
 
 static bool initEscapes;
-static const char *escapes[256];
+static std::string escapes[256];
 
 static void initJsonEscape()
 {
+    // Escape all lower control characters (some get overridden with smaller sequences below)
+    for (int ch=0x00; ch<0x20; ++ch) {
+        char tmpbuf[20];
+        snprintf(tmpbuf, sizeof(tmpbuf), "\\u%04x", ch);
+        escapes[ch] = std::string(tmpbuf);
+    }
+
     escapes[(int)'"'] = "\\\"";
     escapes[(int)'\\'] = "\\\\";
     escapes[(int)'\b'] = "\\b";
@@ -27,6 +34,7 @@ static void initJsonEscape()
     escapes[(int)'\n'] = "\\n";
     escapes[(int)'\r'] = "\\r";
     escapes[(int)'\t'] = "\\t";
+    escapes[(int)'\x7f'] = "\\u007f"; // U+007F DELETE
 
     initEscapes = true;
 }
@@ -39,13 +47,13 @@ static void outputEscape()
 		"static const char *escapes[256] = {\n");
 
 	for (unsigned int i = 0; i < 256; i++) {
-		if (!escapes[i]) {
+		if (escapes[i].empty()) {
 			printf("\tNULL,\n");
 		} else {
 			printf("\t\"");
 
 			unsigned int si;
-			for (si = 0; si < strlen(escapes[i]); si++) {
+			for (si = 0; si < escapes[i].size(); si++) {
 				char ch = escapes[i][si];
 				switch (ch) {
 				case '"':
diff --git a/lib/univalue_escapes.h b/lib/univalue_escapes.h
index 4133b24..74596aa 100644
--- a/lib/univalue_escapes.h
+++ b/lib/univalue_escapes.h
@@ -2,38 +2,38 @@
 #ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
 #define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
 static const char *escapes[256] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
+	"\\u0000",
+	"\\u0001",
+	"\\u0002",
+	"\\u0003",
+	"\\u0004",
+	"\\u0005",
+	"\\u0006",
+	"\\u0007",
 	"\\b",
 	"\\t",
 	"\\n",
-	NULL,
+	"\\u000b",
 	"\\f",
 	"\\r",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
+	"\\u000e",
+	"\\u000f",
+	"\\u0010",
+	"\\u0011",
+	"\\u0012",
+	"\\u0013",
+	"\\u0014",
+	"\\u0015",
+	"\\u0016",
+	"\\u0017",
+	"\\u0018",
+	"\\u0019",
+	"\\u001a",
+	"\\u001b",
+	"\\u001c",
+	"\\u001d",
+	"\\u001e",
+	"\\u001f",
 	NULL,
 	NULL,
 	"\\\"",
@@ -129,7 +129,7 @@ static const char *escapes[256] = {
 	NULL,
 	NULL,
 	NULL,
-	NULL,
+	"\\u007f",
 	NULL,
 	NULL,
 	NULL,
diff --git a/lib/univalue_write.cpp b/lib/univalue_write.cpp
index bce3997..8076ed3 100644
--- a/lib/univalue_write.cpp
+++ b/lib/univalue_write.cpp
@@ -25,10 +25,10 @@ static string json_escape(const string& inS)
         if (escStr)
             outS += escStr;
 
-        else if (isprint(ch))
+        else if (ch < 0x80)
             outS += ch;
 
-        else {
+        else { // TODO handle UTF-8 properly
             char tmpesc[16];
             sprintf(tmpesc, "\\u%04x", ch);
             outS += tmpesc;
diff --git a/test/round1.json b/test/round1.json
new file mode 100644
index 0000000..a711e73
--- /dev/null
+++ b/test/round1.json
@@ -0,0 +1 @@
+["\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 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f"]
diff --git a/test/unitester.cpp b/test/unitester.cpp
index 835556e..c87b86a 100644
--- a/test/unitester.cpp
+++ b/test/unitester.cpp
@@ -20,14 +20,21 @@
 using namespace std;
 string srcdir(JSON_TEST_SRC);
 
+static std::string rtrim(std::string s)
+{
+    s.erase(s.find_last_not_of(" \n\r\t")+1);
+    return s;
+}
+
 static void runtest(string filename, const string& jdata)
 {
         fprintf(stderr, "test %s\n", filename.c_str());
 
         string prefix = filename.substr(0, 4);
 
-        bool wantPass = (prefix == "pass");
+        bool wantPass = (prefix == "pass") || (prefix == "roun");
         bool wantFail = (prefix == "fail");
+        bool wantRoundTrip = (prefix == "roun");
         assert(wantPass || wantFail);
 
         UniValue val;
@@ -38,6 +45,11 @@ static void runtest(string filename, const string& jdata)
         } else {
             assert(testResult == false);
         }
+
+        if (wantRoundTrip) {
+            std::string odata = val.write(0, 0);
+            assert(odata == rtrim(jdata));
+        }
 }
 
 static void runtest_file(const char *filename_)
@@ -102,6 +114,7 @@ static const char *filenames[] = {
         "pass1.json",
         "pass2.json",
         "pass3.json",
+        "round1.json",              // round-trip test
 };
 
 int main (int argc, char *argv[])

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libunivalue.git



More information about the Pkg-bitcoin-commits mailing list