lib/rack/utils.rb in rack-1.6.1 vs lib/rack/utils.rb in rack-1.6.2
- old
+ new
@@ -59,17 +59,22 @@
DEFAULT_SEP = /[&;] */n
class << self
attr_accessor :key_space_limit
+ attr_accessor :param_depth_limit
attr_accessor :multipart_part_limit
end
# The default number of bytes to allow parameter keys to take up.
# This helps prevent a rogue client from flooding a Request.
self.key_space_limit = 65536
+ # Default depth at which the parameter parser will raise an exception for
+ # being too deep. This helps prevent SystemStackErrors
+ self.param_depth_limit = 100
+
# The maximum number of parts a request can contain. Accepting too many part
# can lead to the server running out of file handles.
# Set to `0` for no limit.
# FIXME: RACK_MULTIPART_LIMIT was introduced by mistake and it will be removed in 1.7.0
self.multipart_part_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_LIMIT'] || 128).to_i
@@ -124,11 +129,13 @@
module_function :parse_nested_query
# normalize_params recursively expands parameters into structural types. If
# the structural types represented by two different parameter names are in
# conflict, a ParameterTypeError is raised.
- def normalize_params(params, name, v = nil)
+ def normalize_params(params, name, v = nil, depth = Utils.param_depth_limit)
+ raise RangeError if depth <= 0
+
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
k = $1 || ''
after = $' || ''
return if k.empty?
@@ -144,17 +151,17 @@
elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
child_key = $1
params[k] ||= []
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
if params_hash_type?(params[k].last) && !params[k].last.key?(child_key)
- normalize_params(params[k].last, child_key, v)
+ normalize_params(params[k].last, child_key, v, depth - 1)
else
- params[k] << normalize_params(params.class.new, child_key, v)
+ params[k] << normalize_params(params.class.new, child_key, v, depth - 1)
end
else
params[k] ||= params.class.new
raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
- params[k] = normalize_params(params[k], after, v)
+ params[k] = normalize_params(params[k], after, v, depth - 1)
end
return params
end
module_function :normalize_params