Skip to content

Commit 4b334b5

Browse files
committed
Utils: escapeSpecialChars now handles escape sequences that may break JSON.parse()
Data posted by the client may contain stacktraces and other strings that contain escape sequences such as \n. escapeSpecialChars now handles a wider set of whitespace escape sequences that would otherwise break JSON.parse. May require support for more escape chars, but this might suffice for most cases. Fixes #99
1 parent fbfbc4b commit 4b334b5

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

lib/utils.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ var Log = require('./logger'),
77

88
String.prototype.escapeSpecialChars = function() {
99
return this.replace(/\n/g, '\\n')
10-
.replace(/\\\'/, '\'');
10+
.replace(/\r/g, '\\r')
11+
.replace(/\t/g, '\\t')
12+
.replace(/\f/g, '\\f')
13+
.replace(/\u0008/g, '\\u0008') // \b
14+
.replace(/\v/g, '\\u000b') // \v
15+
.replace(/\0/g, '\\u0000') // \0
16+
.replace(/\\\'/, '\''); // TODO: check why this exists
1117
};
1218

1319
var titleCase = function toTitleCase(str) {

tests/unit/utils_spec.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe('Utilities', function(){
66
assert.equal("Hello", utils.titleCase("hello"));
77
assert.equal("Are You Serious?", utils.titleCase("are you serious?"));
88
});
9-
9+
1010
it('should generate 32 char uuid', function(){
1111
assert.equal(5, utils.uuid().split("-").length);
1212
assert.equal(32 + 4, utils.uuid().length);
@@ -16,24 +16,36 @@ describe('Utilities', function(){
1616
assert.notEqual(utils.uuid(), utils.uuid());
1717
assert.notEqual(utils.uuid(), utils.uuid());
1818
});
19-
19+
2020
it('should generate proper browser string for config', function(){
2121
var chrome_mac = {os: "OS X", os_version: "Mavericks", "browser": "chrome", "browser_version": "latest"};
2222
var chrome_windows = {os: "Windows", os_version: "XP", "browser": "chrome", "browser_version": "latest"};
2323
// var safari_mac = {os: "OS X", os_version: "Mountain Lion", "browser": "safari", "browser_version": "6.1"};
2424
var ie_windows = {os: "Windows", os_version: "7", "browser": "ie", "browser_version": "9.0"};
2525
var iOS = {os: "iOS", os_version: "6.0", device: "iPhone 5"};
2626
var androidConfig = {os: "android", os_version: "4.1"};
27-
27+
2828
assert.equal("OS X Mavericks, Chrome latest", utils.browserString(chrome_mac));
2929
assert.equal("Windows XP, Chrome latest", utils.browserString(chrome_windows));
3030
assert.equal("Windows 7, Internet Explorer 9.0", utils.browserString(ie_windows));
3131
assert.equal("iOS 6.0, iPhone 5", utils.browserString(iOS));
3232
assert.equal("android 4.1", utils.browserString(androidConfig));
3333
});
34-
34+
3535
it('should return number of keys for this object', function(){
3636
assert.equal(0, utils.objectSize({}));
3737
assert.equal(1, utils.objectSize({a: 2}));
3838
});
39+
40+
it('should escape special characters incompatible with JSON.parse', function () {
41+
var testString = '{"tracebacks":[{"actual":null,"message":"Died on test #1 at http://localhost:8888/test/main/globals.js:43:7\n at http://localhost:8888/test/main/globals.js:67:2: Error","testName":"globals: Exported assertions"}]}';
42+
var expectString = '{"tracebacks":[{"actual":null,"message":"Died on test #1 at http://localhost:8888/test/main/globals.js:43:7\\n at http://localhost:8888/test/main/globals.js:67:2: Error","testName":"globals: Exported assertions"}]}';
43+
44+
var malformedJson = '{ "key" : "Bad\njson contains\rall\tsorts\bof\vhorrible\0 & nasty\fescape sequences" }';
45+
var expectJson = { "key" : "Bad\njson contains\rall\tsorts\bof\u000bhorrible\u0000 & nasty\fescape sequences" };
46+
47+
assert.throws(function () { JSON.parse(testString); }, SyntaxError, 'JSON.parse fails');
48+
assert.equal(testString.escapeSpecialChars(), expectString);
49+
assert.equal(JSON.parse(malformedJson.escapeSpecialChars()).key, expectJson.key);
50+
});
3951
});

0 commit comments

Comments
 (0)