[DRE-maint] Bug#1109371: unblock: ruby-rack/3.1.16-0.1
Bastian Germann
bage at debian.org
Wed Jul 16 08:32:04 BST 2025
Package: release.debian.org
Severity: normal
X-Debbugs-Cc: ruby-rack at packages.debian.org
Control: affects -1 + src:ruby-rack
User: release.debian.org at packages.debian.org
Usertags: unblock
Please unblock package ruby-rack.
[ Reason ]
Fixes for RC bugs #1104927 and #1109027.
[ Impact ]
autopkgtests fail, CVE-2025-46727 is exploitable (DoS).
[ Tests ]
autopkgtests pass in unstable.
[ Risks ]
The minor version update also includes other changes including one other
CVE fix. I do not think they pose a significant risk as they also come
with additional unit tests.
[ Checklist ]
[x] all changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in testing
[ Other info ]
I have fixed the bugs via a NMU.
unblock ruby-rack/3.1.16-0.1
-------------- next part --------------
diff -Nru ruby-rack-3.1.12/CHANGELOG.md ruby-rack-3.1.16/CHANGELOG.md
--- ruby-rack-3.1.12/CHANGELOG.md 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/CHANGELOG.md 2025-06-05 00:27:50.000000000 +0200
@@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
+## [3.1.15] - 2025-05-18
+
+- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
+
+## [3.1.14] - 2025-05-06
+
+### Security
+
+- [CVE-2025-46727](https://github.com/rack/rack/security/advisories/GHSA-gjh7-p2fx-99vx) Unbounded parameter parsing in `Rack::QueryParser` can lead to memory exhaustion.
+
+## [3.1.13] - 2025-04-13
+
+- Ensure `Rack::ETag` correctly updates response body. ([#2324](https://github.com/rack/rack/pull/2324), [@ioquatix])
+
## [3.1.12] - 2025-03-11
### Security
@@ -129,6 +143,24 @@
- In `Rack::Files`, ignore the `Range` header if served file is 0 bytes. ([#2159](https://github.com/rack/rack/pull/2159), [@zarqman])
+## [3.0.18] - 2025-05-22
+
+- Fix incorrect backport of optional `CGI::Cookie` support. ([#2335](https://github.com/rack/rack/pull/2335), [@jeremyevans])
+
+## [3.0.17] - 2025-05-18
+
+- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
+
+## [3.0.16] - 2025-05-06
+
+### Security
+
+- [CVE-2025-46727](https://github.com/rack/rack/security/advisories/GHSA-gjh7-p2fx-99vx) Unbounded parameter parsing in `Rack::QueryParser` can lead to memory exhaustion.
+
+## [3.0.15] - 2025-04-13
+
+- Ensure `Rack::ETag` correctly updates response body. ([#2324](https://github.com/rack/rack/pull/2324), [@ioquatix])
+
## [3.0.14] - 2025-03-11
### Security
@@ -141,6 +173,10 @@
- [CVE-2025-27111](https://github.com/rack/rack/security/advisories/GHSA-8cgq-6mh2-7j6v) Possible Log Injection in `Rack::Sendfile`.
+### Fixed
+
+- Remove autoloads for constants no longer shipped with Rack. ([#2269](https://github.com/rack/rack/pull/2269), [@ccutrer](https://github.com/ccutrer))
+
## [3.0.12] - 2025-02-12
### Security
@@ -275,7 +311,7 @@
- Remove deprecated Rack::Request::SCHEME_WHITELIST. ([@jeremyevans])
- Remove internal cookie deletion using pattern matching, there are very few practical cases where it would be useful and browsers handle it correctly without us doing anything special. ([#1844](https://github.com/rack/rack/pull/1844), [@ioquatix])
- Remove `rack.version` as it comes too late to be useful. ([#1938](https://github.com/rack/rack/pull/1938), [@ioquatix])
-- Extract `rackup` command, `Rack::Server`, `Rack::Handler`, `Rack::Lobster` and related code into a separate gem. ([#1937](https://github.com/rack/rack/pull/1937), [@ioquatix])
+- Extract `rackup` command, `Rack::Server`, `Rack::Handler` and related code into a separate gem. ([#1937](https://github.com/rack/rack/pull/1937), [@ioquatix])
### Added
@@ -323,6 +359,20 @@
- Fix multipart filename generation for filenames that contain spaces. Encode spaces as "%20" instead of "+" which will be decoded properly by the multipart parser. ([#1736](https://github.com/rack/rack/pull/1645), [@muirdm](https://github.com/muirdm))
- `Rack::Request#scheme` returns `ws` or `wss` when one of the `X-Forwarded-Scheme` / `X-Forwarded-Proto` headers is set to `ws` or `wss`, respectively. ([#1730](https://github.com/rack/rack/issues/1730), [@erwanst](https://github.com/erwanst))
+## [2.2.16] - 2025-05-22
+
+- Fix incorrect backport of optional `CGI::Cookie` support. ([#2335](https://github.com/rack/rack/pull/2335), [@jeremyevans])
+
+## [2.2.15] - 2025-05-18
+
+- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
+
+## [2.2.14] - 2025-05-06
+
+### Security
+
+- [CVE-2025-46727](https://github.com/rack/rack/security/advisories/GHSA-gjh7-p2fx-99vx) Unbounded parameter parsing in `Rack::QueryParser` can lead to memory exhaustion.
+
## [2.2.13] - 2025-03-11
### Security
@@ -1104,3 +1154,4 @@
[@wjordan]: https://github.com/wjordan "Will Jordan"
[@BlakeWilliams]: https://github.com/BlakeWilliams "Blake Williams"
[@davidstosik]: https://github.com/davidstosik "David Stosik"
+[@earlopain]: https://github.com/earlopain "Earlopain"
diff -Nru ruby-rack-3.1.12/debian/changelog ruby-rack-3.1.16/debian/changelog
--- ruby-rack-3.1.12/debian/changelog 2025-03-19 16:53:01.000000000 +0100
+++ ruby-rack-3.1.16/debian/changelog 2025-07-15 18:00:20.000000000 +0200
@@ -1,3 +1,12 @@
+ruby-rack (3.1.16-0.1) unstable; urgency=medium
+
+ * Non-maintainer upload
+ * New upstream version 3.1.16 (Closes: #1104927, #1107363),
+ fixes CVE-2025-46727, CVE-2025-49007
+ * Remove ruby-bacon from autopkgtests (Closes: #1109027)
+
+ -- Bastian Germann <bage at debian.org> Tue, 15 Jul 2025 18:00:20 +0200
+
ruby-rack (3.1.12-1) unstable; urgency=medium
* Team upload
diff -Nru ruby-rack-3.1.12/debian/tests/control ruby-rack-3.1.16/debian/tests/control
--- ruby-rack-3.1.12/debian/tests/control 2025-03-16 18:51:46.000000000 +0100
+++ ruby-rack-3.1.16/debian/tests/control 2025-07-15 18:00:20.000000000 +0200
@@ -2,5 +2,5 @@
Depends: @, curl, ruby-rackup, ruby-webrick
Test-Command: gem2deb-test-runner
-Depends: @, gem2deb-test-runner, rake, ruby-bacon, ruby-minitest-global-expectations, ruby-webrick
+Depends: @, gem2deb-test-runner, rake, ruby-minitest-global-expectations, ruby-webrick
Restrictions: allow-stderr
diff -Nru ruby-rack-3.1.12/.github/workflows/test.yaml ruby-rack-3.1.16/.github/workflows/test.yaml
--- ruby-rack-3.1.12/.github/workflows/test.yaml 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/.github/workflows/test.yaml 2025-06-05 00:27:50.000000000 +0200
@@ -21,6 +21,7 @@
- '3.1'
- '3.2'
- '3.3'
+ - '3.4'
- jruby-head
- truffleruby-head
include:
diff -Nru ruby-rack-3.1.12/lib/rack/etag.rb ruby-rack-3.1.16/lib/rack/etag.rb
--- ruby-rack-3.1.12/lib/rack/etag.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/lib/rack/etag.rb 2025-06-05 00:27:50.000000000 +0200
@@ -32,6 +32,9 @@
body = body.to_ary
digest = digest_body(body)
headers[ETAG_STRING] = %(W/"#{digest}") if digest
+
+ # Body was modified, so we need to re-assign it:
+ response[2] = body
end
unless headers[CACHE_CONTROL]
diff -Nru ruby-rack-3.1.12/lib/rack/mock_response.rb ruby-rack-3.1.16/lib/rack/mock_response.rb
--- ruby-rack-3.1.12/lib/rack/mock_response.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/lib/rack/mock_response.rb 2025-06-05 00:27:50.000000000 +0200
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require 'cgi/cookie'
require 'time'
require_relative 'response'
@@ -11,6 +10,36 @@
# MockRequest.
class MockResponse < Rack::Response
+ begin
+ # Recent versions of the CGI gem may not provide `CGI::Cookie`.
+ require 'cgi/cookie'
+ Cookie = CGI::Cookie
+ rescue LoadError
+ class Cookie
+ attr_reader :name, :value, :path, :domain, :expires, :secure
+
+ def initialize(args)
+ @name = args["name"]
+ @value = args["value"]
+ @path = args["path"]
+ @domain = args["domain"]
+ @expires = args["expires"]
+ @secure = args["secure"]
+ end
+
+ def method_missing(method_name, *args, &block)
+ @value.send(method_name, *args, &block)
+ end
+ # :nocov:
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
+ # :nocov:
+
+ def respond_to_missing?(method_name, include_all = false)
+ @value.respond_to?(method_name, include_all) || super
+ end
+ end
+ end
+
class << self
alias [] new
end
@@ -83,7 +112,7 @@
Array(set_cookie_header).each do |cookie|
cookie_name, cookie_filling = cookie.split('=', 2)
cookie_attributes = identify_cookie_attributes cookie_filling
- parsed_cookie = CGI::Cookie.new(
+ parsed_cookie = Cookie.new(
'name' => cookie_name.strip,
'value' => cookie_attributes.fetch('value'),
'path' => cookie_attributes.fetch('path', nil),
@@ -100,7 +129,7 @@
def identify_cookie_attributes(cookie_filling)
cookie_bits = cookie_filling.split(';')
cookie_attributes = Hash.new
- cookie_attributes.store('value', cookie_bits[0].strip)
+ cookie_attributes.store('value', Array(cookie_bits[0].strip))
cookie_bits.drop(1).each do |bit|
if bit.include? '='
cookie_attribute, attribute_value = bit.split('=', 2)
diff -Nru ruby-rack-3.1.12/lib/rack/multipart/parser.rb ruby-rack-3.1.16/lib/rack/multipart/parser.rb
--- ruby-rack-3.1.12/lib/rack/multipart/parser.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/lib/rack/multipart/parser.rb 2025-06-05 00:27:50.000000000 +0200
@@ -31,10 +31,12 @@
Error = BoundaryTooLongError
EOL = "\r\n"
+ FWS = /[ \t]+(?:\r\n[ \t]+)?/ # whitespace with optional folding
+ HEADER_VALUE = "(?:[^\r\n]|\r\n[ \t])*" # anything but a non-folding CRLF
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
- MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
- MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:(.*)(?=#{EOL}(\S|\z))/ni
- MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
+ MULTIPART_CONTENT_TYPE = /^Content-Type:#{FWS}?(#{HEADER_VALUE})/ni
+ MULTIPART_CONTENT_DISPOSITION = /^Content-Disposition:#{FWS}?(#{HEADER_VALUE})/ni
+ MULTIPART_CONTENT_ID = /^Content-ID:#{FWS}?(#{HEADER_VALUE})/ni
class Parser
BUFSIZE = 1_048_576
diff -Nru ruby-rack-3.1.12/lib/rack/query_parser.rb ruby-rack-3.1.16/lib/rack/query_parser.rb
--- ruby-rack-3.1.12/lib/rack/query_parser.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/lib/rack/query_parser.rb 2025-06-05 00:27:50.000000000 +0200
@@ -21,21 +21,47 @@
include BadRequest
end
- # ParamsTooDeepError is the error that is raised when params are recursively
- # nested over the specified limit.
- class ParamsTooDeepError < RangeError
+ # QueryLimitError is for errors raised when the query provided exceeds one
+ # of the query parser limits.
+ class QueryLimitError < RangeError
include BadRequest
end
- def self.make_default(param_depth_limit)
- new Params, param_depth_limit
+ # ParamsTooDeepError is the old name for the error that is raised when params
+ # are recursively nested over the specified limit. Make it the same as
+ # as QueryLimitError, so that code that rescues ParamsTooDeepError error
+ # to handle bad query strings also now handles other limits.
+ ParamsTooDeepError = QueryLimitError
+
+ def self.make_default(param_depth_limit, **options)
+ new(Params, param_depth_limit, **options)
end
attr_reader :param_depth_limit
- def initialize(params_class, param_depth_limit)
+ env_int = lambda do |key, val|
+ if str_val = ENV[key]
+ begin
+ val = Integer(str_val, 10)
+ rescue ArgumentError
+ raise ArgumentError, "non-integer value provided for environment variable #{key}"
+ end
+ end
+
+ val
+ end
+
+ BYTESIZE_LIMIT = env_int.call("RACK_QUERY_PARSER_BYTESIZE_LIMIT", 4194304)
+ private_constant :BYTESIZE_LIMIT
+
+ PARAMS_LIMIT = env_int.call("RACK_QUERY_PARSER_PARAMS_LIMIT", 4096)
+ private_constant :PARAMS_LIMIT
+
+ def initialize(params_class, param_depth_limit, bytesize_limit: BYTESIZE_LIMIT, params_limit: PARAMS_LIMIT)
@params_class = params_class
@param_depth_limit = param_depth_limit
+ @bytesize_limit = bytesize_limit
+ @params_limit = params_limit
end
# Stolen from Mongrel, with some small modifications:
@@ -47,7 +73,7 @@
params = make_params
- (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
+ check_query_string(qs, separator).split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
next if p.empty?
k, v = p.split('=', 2).map!(&unescaper)
@@ -74,7 +100,7 @@
params = make_params
unless qs.nil? || qs.empty?
- (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
+ check_query_string(qs, separator).split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
k, v = p.split('=', 2).map! { |s| unescape(s) }
_normalize_params(params, k, v, 0)
@@ -189,6 +215,22 @@
true
end
+ def check_query_string(qs, sep)
+ if qs
+ if qs.bytesize > @bytesize_limit
+ raise QueryLimitError, "total query size (#{qs.bytesize}) exceeds limit (#{@bytesize_limit})"
+ end
+
+ if (param_count = qs.count(sep.is_a?(String) ? sep : '&')) >= @params_limit
+ raise QueryLimitError, "total number of query parameters (#{param_count+1}) exceeds limit (#{@params_limit})"
+ end
+
+ qs
+ else
+ ''
+ end
+ end
+
def unescape(string, encoding = Encoding::UTF_8)
URI.decode_www_form_component(string, encoding)
end
diff -Nru ruby-rack-3.1.12/lib/rack/version.rb ruby-rack-3.1.16/lib/rack/version.rb
--- ruby-rack-3.1.12/lib/rack/version.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/lib/rack/version.rb 2025-06-05 00:27:50.000000000 +0200
@@ -12,7 +12,7 @@
# so it should be enough just to <tt>require 'rack'</tt> in your code.
module Rack
- RELEASE = "3.1.12"
+ RELEASE = "3.1.16"
# Return the Rack release as a dotted string.
def self.release
diff -Nru ruby-rack-3.1.12/README.md ruby-rack-3.1.16/README.md
--- ruby-rack-3.1.12/README.md 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/README.md 2025-06-05 00:27:50.000000000 +0200
@@ -183,6 +183,33 @@
Rack exposes several configuration parameters to control various features of the
implementation.
+### `RACK_QUERY_PARSER_BYTESIZE_LIMIT`
+
+This environment variable sets the default for the maximum query string bytesize
+that `Rack::QueryParser` will attempt to parse. Attempts to use a query string
+that exceeds this number of bytes will result in a
+`Rack::QueryParser::QueryLimitError` exception. If this enviroment variable is
+provided, it must be an integer, or `Rack::QueryParser` will raise an exception.
+
+The default limit can be overridden on a per-`Rack::QueryParser` basis using
+the `bytesize_limit` keyword argument when creating the `Rack::QueryParser`.
+
+### `RACK_QUERY_PARSER_PARAMS_LIMIT`
+
+This environment variable sets the default for the maximum number of query
+parameters that `Rack::QueryParser` will attempt to parse. Attempts to use a
+query string with more than this many query parameters will result in a
+`Rack::QueryParser::QueryLimitError` exception. If this enviroment variable is
+provided, it must be an integer, or `Rack::QueryParser` will raise an exception.
+
+The default limit can be overridden on a per-`Rack::QueryParser` basis using
+the `params_limit` keyword argument when creating the `Rack::QueryParser`.
+
+This is implemented by counting the number of parameter separators in the
+query string, before attempting parsing, so if the same parameter key is
+used multiple times in the query, each counts as a separate parameter for
+this check.
+
### `param_depth_limit`
```ruby
diff -Nru ruby-rack-3.1.12/test/spec_etag.rb ruby-rack-3.1.16/test/spec_etag.rb
--- ruby-rack-3.1.12/test/spec_etag.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_etag.rb 2025-06-05 00:27:50.000000000 +0200
@@ -28,6 +28,16 @@
response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\""
end
+ it "returns a valid response body when using a linted app" do
+ app = lambda { |env| [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] }
+ response = etag(Rack::Lint.new(app)).call(request)
+ response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\""
+
+ response[2].each do |chunk|
+ chunk.must_equal "Hello, World!"
+ end
+ end
+
it "set etag if none is set if status is 201" do
app = lambda { |env| [201, { 'content-type' => 'text/plain' }, ["Hello, World!"]] }
response = etag(app).call(request)
diff -Nru ruby-rack-3.1.12/test/spec_headers.rb ruby-rack-3.1.16/test/spec_headers.rb
--- ruby-rack-3.1.12/test/spec_headers.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_headers.rb 2025-06-05 00:27:50.000000000 +0200
@@ -220,8 +220,8 @@
def test_inspect
%i'inspect to_s'.each do |meth|
- assert_equal '{}', @h.send(meth)
- assert_equal '{"ab"=>"1", "cd"=>"2", "3"=>"4"}', @fh.send(meth)
+ assert_equal({}.inspect, @h.send(meth))
+ assert_equal({"ab"=>"1", "cd"=>"2", "3"=>"4"}.inspect, @fh.send(meth))
end
end
diff -Nru ruby-rack-3.1.12/test/spec_mock_response.rb ruby-rack-3.1.16/test/spec_mock_response.rb
--- ruby-rack-3.1.12/test/spec_mock_response.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_mock_response.rb 2025-06-05 00:27:50.000000000 +0200
@@ -84,6 +84,7 @@
it "provides access to session cookies" do
res = Rack::MockRequest.new(app).get("")
session_cookie = res.cookie("session_test")
+ session_cookie[0].must_equal "session_test"
session_cookie.value[0].must_equal "session_test"
session_cookie.domain.must_equal "test.com"
session_cookie.path.must_equal "/"
diff -Nru ruby-rack-3.1.12/test/spec_multipart.rb ruby-rack-3.1.16/test/spec_multipart.rb
--- ruby-rack-3.1.12/test/spec_multipart.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_multipart.rb 2025-06-05 00:27:50.000000000 +0200
@@ -334,7 +334,7 @@
it "ignores content-disposition values over to 1536 bytes" do
x = content_disposition_parse.call("a=#{'a'*1510}; filename=\"bar\"; name=\"file\"")
- x.must_equal "text/plain"=>[""]
+ x.must_equal "application/pdf"=>[""]
end
it 'raises an EOF error on content-length mismatch' do
@@ -955,7 +955,7 @@
data = <<-EOF
--AaB03x\r
content-type: text/plain\r
-content-disposition: attachment; name="quoted\\\\chars\\"in\rname"\r
+content-disposition: attachment; name="quoted\\\\chars\\"in\tname"\r
\r
true\r
--AaB03x--\r
@@ -968,7 +968,7 @@
}
env = Rack::MockRequest.env_for("/", options)
params = Rack::Multipart.parse_multipart(env)
- params["quoted\\chars\"in\rname"].must_equal 'true'
+ params["quoted\\chars\"in\tname"].must_equal 'true'
end
it "supports mixed case metadata" do
diff -Nru ruby-rack-3.1.12/test/spec_query_parser.rb ruby-rack-3.1.16/test/spec_query_parser.rb
--- ruby-rack-3.1.12/test/spec_query_parser.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_query_parser.rb 2025-06-05 00:27:50.000000000 +0200
@@ -7,11 +7,30 @@
end
describe Rack::QueryParser do
- query_parser ||= Rack::QueryParser.make_default(8)
-
it "can normalize values with missing values" do
+ query_parser = Rack::QueryParser.make_default(8)
query_parser.parse_nested_query("a=a").must_equal({"a" => "a"})
query_parser.parse_nested_query("a=").must_equal({"a" => ""})
query_parser.parse_nested_query("a").must_equal({"a" => nil})
end
+
+ it "accepts bytesize_limit to specify maximum size of query string to parse" do
+ query_parser = Rack::QueryParser.make_default(32, bytesize_limit: 3)
+ query_parser.parse_query("a=a").must_equal({"a" => "a"})
+ query_parser.parse_nested_query("a=a").must_equal({"a" => "a"})
+ query_parser.parse_nested_query("a=a", '&').must_equal({"a" => "a"})
+ proc { query_parser.parse_query("a=aa") }.must_raise Rack::QueryParser::QueryLimitError
+ proc { query_parser.parse_nested_query("a=aa") }.must_raise Rack::QueryParser::QueryLimitError
+ proc { query_parser.parse_nested_query("a=aa", '&') }.must_raise Rack::QueryParser::QueryLimitError
+ end
+
+ it "accepts params_limit to specify maximum number of query parameters to parse" do
+ query_parser = Rack::QueryParser.make_default(32, params_limit: 2)
+ query_parser.parse_query("a=a&b=b").must_equal({"a" => "a", "b" => "b"})
+ query_parser.parse_nested_query("a=a&b=b").must_equal({"a" => "a", "b" => "b"})
+ query_parser.parse_nested_query("a=a&b=b", '&').must_equal({"a" => "a", "b" => "b"})
+ proc { query_parser.parse_query("a=a&b=b&c=c") }.must_raise Rack::QueryParser::QueryLimitError
+ proc { query_parser.parse_nested_query("a=a&b=b&c=c", '&') }.must_raise Rack::QueryParser::QueryLimitError
+ proc { query_parser.parse_query("b[]=a&b[]=b&b[]=c") }.must_raise Rack::QueryParser::QueryLimitError
+ end
end
diff -Nru ruby-rack-3.1.12/test/spec_request.rb ruby-rack-3.1.16/test/spec_request.rb
--- ruby-rack-3.1.12/test/spec_request.rb 2025-03-10 22:21:44.000000000 +0100
+++ ruby-rack-3.1.16/test/spec_request.rb 2025-06-05 00:27:50.000000000 +0200
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require_relative 'helper'
-require 'cgi'
+require 'cgi/escape'
require 'forwardable'
require 'securerandom'
@@ -1910,6 +1910,9 @@
class NonDelegate < Rack::Request
def delegate?; false; end
+ def query_parser
+ Rack::QueryParser.make_default(Rack::Utils.param_depth_limit, bytesize_limit: 2**30)
+ end
end
def make_request(env)
@@ -1931,6 +1934,10 @@
end
def delegate?; true; end
+
+ def query_parser
+ Rack::QueryParser.make_default(Rack::Utils.param_depth_limit, bytesize_limit: 2**30)
+ end
end
def make_request(env)
More information about the Pkg-ruby-extras-maintainers
mailing list