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