From 60a6178131afec97b68c9a45bc24459f7b8bd905 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 4 Nov 2013 23:36:15 -0500 Subject: Fix #14492: More correct jQuery.parseJSON. Close gh-1419. --- src/ajax/parseJSON.js | 53 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'src/ajax') diff --git a/src/ajax/parseJSON.js b/src/ajax/parseJSON.js index 735015c9f..69b5c837d 100644 --- a/src/ajax/parseJSON.js +++ b/src/ajax/parseJSON.js @@ -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; - } - - if ( typeof data === "string" ) { + var requireNonComma, + depth = null, + str = jQuery.trim( data + "" ); - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); + // 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 ) { - 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, "")) ) { + // Force termination if we see a misplaced comma + if ( requireNonComma && comma ) { + depth = 0; + } - return ( new Function( "return " + data ) )(); - } + // Perform no more replacements after returning to outermost depth + if ( depth === 0 ) { + return token; } - } - jQuery.error( "Invalid JSON: " + data ); + // 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; -- cgit v1.2.3