Headline
CVE-2022-32511: What's the difference between JSON.load and JSON.parse methods of Ruby lib?
jmespath.rb (aka JMESPath for Ruby) before 1.6.1 uses JSON.load in a situation where JSON.parse is preferable.
Here load the source codes click me
# File ext/json/lib/json/common.rb, line 323
def load(source, proc = nil, options = {})
opts = load_default_options.merge options
if source.respond_to? :to_str
source = source.to_str
elsif source.respond_to? :to_io
source = source.to_io.read
elsif source.respond_to?(:read)
source = source.read
end
if opts[:allow_blank] && (source.nil? || source.empty?)
source = 'null'
end
result = parse(source, opts)
recurse_proc(result, &proc) if proc
result
end
The first line within the method:
opts = load_default_options.merge options
We can call the JSON#load_default_options in the console:
JSON.load_default_options
=> {:max_nesting=>false, :allow_nan=>true, :quirks_mode=>true, :create_additions=>true}
We can see there’re four default options, what do they mean, we can get some from here click me:
- max_nesting: The maximum depth of nesting allowed in the parsed data structures. Disable depth checking with :max_nesting => false. It defaults to 100./
- allow_nan: If set to true, allow NaN, Infinity and -Infinity in defiance of RFC 7159 to be parsed by the Parser. This option defaults to false.
- symbolize_names: If set to true, returns symbols for the names (keys) in a JSON object. Otherwise, strings are returned. Strings are the default.
- create_additions: If set to false, the Parser doesn’t create additions even if a matching class and create_id was found. This option defaults to false.
- object_class: Defaults to Hash
- array_class: Defaults to Array
WHY
referring to JSON#parse, back to see the source codes of JSON#load, The third to last line, there is result = parse(source, opts), So load actually is a parse with four default options.
That is the reason:
JSON.load("123") #=> 123
JSON.parse("123", quirks_mode: true) #=> 123
another way, if the object to be parsed responds to to_io meaning is a File, load still makes sense. However, parse do not.
Related news
jmespath.rb (aka JMESPath for Ruby) before 1.6.1 uses JSON.load in a situation where JSON.parse is preferable.