Skip to content

Commit

Permalink
Merge pull request litecoin-project#14 from laanwj/2015_11_escape_plan
Browse files Browse the repository at this point in the history
Escape all control characters
  • Loading branch information
Jeff Garzik committed Dec 2, 2015
2 parents 46098ee + 7482163 commit 5e7985a
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 35 deletions.
3 changes: 2 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ TEST_FILES = \
$(TEST_DATA_DIR)/fail9.json \
$(TEST_DATA_DIR)/pass1.json \
$(TEST_DATA_DIR)/pass2.json \
$(TEST_DATA_DIR)/pass3.json
$(TEST_DATA_DIR)/pass3.json \
$(TEST_DATA_DIR)/round1.json

EXTRA_DIST=$(TEST_FILES) $(GEN_SRCS)
14 changes: 11 additions & 3 deletions gen/gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@
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";
escapes[(int)'\f'] = "\\f";
escapes[(int)'\n'] = "\\n";
escapes[(int)'\r'] = "\\r";
escapes[(int)'\t'] = "\\t";
escapes[(int)'\x7f'] = "\\u007f"; // U+007F DELETE

initEscapes = true;
}
Expand All @@ -38,13 +46,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 '"':
Expand Down
56 changes: 28 additions & 28 deletions lib/univalue_escapes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
"\\\"",
Expand Down Expand Up @@ -129,7 +129,7 @@ static const char *escapes[256] = {
NULL,
NULL,
NULL,
NULL,
"\\u007f",
NULL,
NULL,
NULL,
Expand Down
4 changes: 2 additions & 2 deletions lib/univalue_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,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;
Expand Down
1 change: 1 addition & 0 deletions test/round1.json
Original file line number Diff line number Diff line change
@@ -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"]
15 changes: 14 additions & 1 deletion test/unitester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ static bool test_failed = false;

#define d_assert(expr) { if (!(expr)) { test_failed = true; fprintf(stderr, "%s failed\n", filename.c_str()); } }

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)
{
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;
Expand All @@ -39,6 +46,11 @@ static void runtest(string filename, const string& jdata)
} else {
d_assert(testResult == false);
}

if (wantRoundTrip) {
std::string odata = val.write(0, 0);
assert(odata == rtrim(jdata));
}
}

static void runtest_file(const char *filename_)
Expand Down Expand Up @@ -106,6 +118,7 @@ static const char *filenames[] = {
"pass1.json",
"pass2.json",
"pass3.json",
"round1.json", // round-trip test
};

int main (int argc, char *argv[])
Expand Down

0 comments on commit 5e7985a

Please sign in to comment.