Prevent a crash in Safari when calling String#evalJSON(true) on very large strings. Add String#isJSON. Closes #7834. [Tobie Langel]

This commit is contained in:
Thomas Fuchs 2007-06-17 16:03:38 +00:00
parent 1e13c1d0b7
commit 9ff57b042d
3 changed files with 31 additions and 2 deletions

View File

@ -1,5 +1,7 @@
*SVN*
* Prevent a crash in Safari when calling String#evalJSON(true) on very large strings. Add String#isJSON. Closes #7834. [Tobie Langel]
* Prevent a crash in Safari 1.3 on String#stripScripts and String#extractScripts. Closes #8332. [grant, Tobie Langel]
* Allow JSON data to contain line breaks. Closes #8271. [pijyster, Tobie Langel]

View File

@ -167,11 +167,15 @@ Object.extend(String.prototype, {
return this.sub(filter || Prototype.JSONFilter, '#{1}');
},
isJSON: function() {
var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
},
evalJSON: function(sanitize) {
var json = this.unfilterJSON();
try {
if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json)))
return eval('(' + json + ')');
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
},

View File

@ -415,11 +415,32 @@
assertEqual('\"\"', ''.toJSON());
assertEqual('\"test\"', 'test'.toJSON());
}},
testIsJSON: function() {with(this) {
assert(''.isJSON());
assert('"foo"'.isJSON());
assert('{}'.isJSON());
assert('[]'.isJSON());
assert('null'.isJSON());
assert('123'.isJSON());
assert('true'.isJSON());
assert('false'.isJSON());
assert('"\\""'.isJSON());
assert(!'\\"'.isJSON());
assert(!'new'.isJSON());
assert(!'\u0028\u0029'.isJSON());
// we use '@' as a placeholder for characters authorized only inside brackets,
// so this tests make sure it is considered as authorized.
assert(!'@'.isJSON());
}},
testEvalJSON: function() {with(this) {
var valid = '{test: \n\r"hello world!"}';
var invalid = '{test: "hello world!"';
var dangerous = '{});attackTarget = "attack succeeded!";({}';
var longString = '"' + '123456789\\"'.times(1000) + '"';
var object = '{' + longString + ': ' + longString + '},';
var huge = '[' + object.times(100) + '{"test": 123}]';
assertEqual('hello world!', valid.evalJSON().test);
assertEqual('hello world!', valid.evalJSON(true).test);
@ -439,6 +460,8 @@
Prototype.JSONFilter = /^\/\*([\s\S]*)\*\/$/; // test custom delimiters.
assertEqual('hello world!', ('/*' + valid + '*/').evalJSON().test);
Prototype.JSONFilter = temp;
assertMatch(123, huge.evalJSON(true).last().test);
}}
}, 'testlog');
// ]]>