Fix #14492: More correct jQuery.parseJSON. Close gh-1419.

This commit is contained in:
Richard Gibson
2013-11-04 23:36:15 -05:00
parent ef7f8f1ead
commit 60a6178131
3 changed files with 103 additions and 30 deletions

View File

@@ -2,39 +2,48 @@ define([
"../core"
], function( jQuery ) {
var rvalidchars = /^[\],:{}\s]*$/,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g;
var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
jQuery.parseJSON = function( data ) {
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
// Support: Android 2.3
// Workaround failure to string-cast null input
return window.JSON.parse( data + "" );
}
if ( data === null ) {
return data;
}
var requireNonComma,
depth = null,
str = jQuery.trim( data + "" );
if ( typeof data === "string" ) {
// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
// after removing valid tokens
return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
// Make sure leading/trailing whitespace is removed (IE can't handle it)
data = jQuery.trim( data );
if ( data ) {
// Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js
if ( rvalidchars.test( data.replace( rvalidescape, "@" )
.replace( rvalidtokens, "]" )
.replace( rvalidbraces, "")) ) {
return ( new Function( "return " + data ) )();
}
// Force termination if we see a misplaced comma
if ( requireNonComma && comma ) {
depth = 0;
}
}
jQuery.error( "Invalid JSON: " + data );
// Perform no more replacements after returning to outermost depth
if ( depth === 0 ) {
return token;
}
// Commas must not follow "[", "{", or ","
requireNonComma = open || comma;
// Determine new depth
// array/object open ("[" or "{"): depth += true - false (increment)
// array/object close ("]" or "}"): depth += false - true (decrement)
// other cases ("," or primitive): depth += true - true (numeric cast)
depth += !close - !open;
// Remove this token
return "";
}) ) ?
( Function( "return " + str ) )() :
jQuery.error( "Invalid JSON: " + data );
};
return jQuery.parseJSON;