rack 2.0.9 → 2.0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b0768103afcff14e04b93b0f4d359289b26b21d2ac7c80a42a31d74c0467e23
4
- data.tar.gz: 84164353b9192f85a1ee40813ce9402dfca3f4850704718c6b103a3f062bc813
3
+ metadata.gz: 3418ae80f8de1427728a2e17364b9c8d124f2efb3e2ce6ebd2fbf6ba08c76efa
4
+ data.tar.gz: 2ba9cd20d9b168c583813b6c1e0d39cb6b8f33d110605b2c28c97dac60718cfc
5
5
  SHA512:
6
- metadata.gz: fe9cdddbc606c1898db93ab17308de607d0ac9f93d6cf0554e444eea18901d144740718aedfe37b6a9353dae5169152315c00a2b971394fa2d6785ae0ad82203
7
- data.tar.gz: e06d452659054f852edd963fb9ec776e450526f7918dedb937298b4f0ca938eeb047901d3c48c463a5ce1291070221dda1602cf96b042603c4e531cc6873dcbd
6
+ metadata.gz: ff2af28dd5b0b338c61d95eb793ac577098803374db893f739402ebd41ee75a1ebab4eba32474e2e68014475f0f5e71ad8fff3b4270fe3c9f281eaf3024c4b32
7
+ data.tar.gz: 6ebf297cb644ab382bcf02d3c0a7b4376223222ccaca426e093ecba02a4a9302324199ecd43788aa5f248b060f3c37a16fe820ebb9b46570dc2831627ef486d0
data/HISTORY.md CHANGED
@@ -1,3 +1,18 @@
1
+ Thu Mar 2 14:50:46 2023 Aaron Patterson <tenderlove@ruby-lang.org>
2
+
3
+ * [CVE-2023-27530] Introduce multipart_total_part_limit to limit total parts
4
+
5
+ Tue Jan 17 12:27:04 2023 Aaron Patterson <tenderlove@ruby-lang.org>
6
+
7
+ * [CVE-2022-44571] Fix ReDoS vulnerability in multipart parser
8
+ * [CVE-2022-44570] Fix ReDoS in Rack::Utils.get_byte_ranges
9
+ * [CVE-2022-44572] Forbid control characters in attributes (also ReDoS)
10
+
11
+ Fri May 27 08:27:04 2022 Aaron Patterson <tenderlove@ruby-lang.org>
12
+
13
+ * [CVE-2022-30123] Fix shell escaping issue in Common Logger
14
+ * [CVE-2022-30122] Restrict parsing of broken MIME attachments
15
+
1
16
  Sun Dec 4 18:48:03 2015 Jeremy Daer <jeremydaer@gmail.com>
2
17
 
3
18
  * First-party "SameSite" cookies. Browsers omit SameSite cookies
data/README.rdoc CHANGED
@@ -189,16 +189,30 @@ This helps prevent a rogue client from flooding a Request.
189
189
 
190
190
  Default to 65536 characters (4 kiB in worst case).
191
191
 
192
- === multipart_part_limit
192
+ === multipart_file_limit
193
193
 
194
- The maximum number of parts a request can contain.
194
+ The maximum number of parts with a filename a request can contain.
195
195
  Accepting too many part can lead to the server running out of file handles.
196
196
 
197
197
  The default is 128, which means that a single request can't upload more than 128 files at once.
198
198
 
199
199
  Set to 0 for no limit.
200
200
 
201
- Can also be set via the RACK_MULTIPART_PART_LIMIT environment variable.
201
+ Can also be set via the +RACK_MULTIPART_FILE_LIMIT+ environment variable.
202
+
203
+ (This is also aliased as +multipart_part_limit+ and +RACK_MULTIPART_PART_LIMIT+ for compatibility)
204
+
205
+ === multipart_total_part_limit
206
+
207
+ The maximum total number of parts a request can contain of any type, including
208
+ both file and non-file form fields.
209
+
210
+ The default is 4096, which means that a single request can't contain more than
211
+ 4096 parts.
212
+
213
+ Set to 0 for no limit.
214
+
215
+ Can also be set via the +RACK_MULTIPART_TOTAL_PART_LIMIT+ environment variable.
202
216
 
203
217
  == History
204
218
 
data/SPEC CHANGED
@@ -60,8 +60,8 @@ below.
60
60
  the presence or absence of the
61
61
  appropriate HTTP header in the
62
62
  request. See
63
- <a href="https://tools.ietf.org/html/rfc3875#section-4.1.18">
64
- RFC3875 section 4.1.18</a> for
63
+ {https://tools.ietf.org/html/rfc3875#section-4.1.18
64
+ RFC3875 section 4.1.18} for
65
65
  specific behavior.
66
66
  In addition to this, the Rack environment must include these
67
67
  Rack-specific variables:
@@ -98,13 +98,12 @@ Rack-specific variables:
98
98
  Additional environment specifications have approved to
99
99
  standardized middleware APIs. None of these are required to
100
100
  be implemented by the server.
101
- <tt>rack.session</tt>:: A hash like interface for storing
102
- request session data.
101
+ <tt>rack.session</tt>:: A hash like interface for storing request session data.
103
102
  The store must implement:
104
- store(key, value) (aliased as []=);
105
- fetch(key, default = nil) (aliased as []);
106
- delete(key);
107
- clear;
103
+ store(key, value) (aliased as []=);
104
+ fetch(key, default = nil) (aliased as []);
105
+ delete(key);
106
+ clear;
108
107
  <tt>rack.logger</tt>:: A common object interface for logging messages.
109
108
  The object must implement:
110
109
  info(message, &block)
@@ -54,7 +54,10 @@ module Rack
54
54
  length,
55
55
  now - began_at ]
56
56
 
57
+ msg.gsub!(/[^[:print:]\n]/) { |c| "\\x#{c.ord}" }
58
+
57
59
  logger = @logger || env[RACK_ERRORS]
60
+
58
61
  # Standard library logger doesn't support write but it supports << which actually
59
62
  # calls to write on the log device without formatting
60
63
  if logger.respond_to?(:write)
data/lib/rack/lint.rb CHANGED
@@ -295,7 +295,7 @@ module Rack
295
295
  check_hijack env
296
296
 
297
297
  ## * The <tt>REQUEST_METHOD</tt> must be a valid token.
298
- assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD]}") {
298
+ assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD].dump}") {
299
299
  env[REQUEST_METHOD] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
300
300
  }
301
301
 
@@ -3,6 +3,7 @@ require 'rack/utils'
3
3
  module Rack
4
4
  module Multipart
5
5
  class MultipartPartLimitError < Errno::EMFILE; end
6
+ class MultipartTotalPartLimitError < StandardError; end
6
7
 
7
8
  class Parser
8
9
  BUFSIZE = 16384
@@ -138,7 +139,8 @@ module Rack
138
139
  end
139
140
 
140
141
  @mime_parts[mime_index] = klass.new(body, head, filename, content_type, name)
141
- check_open_files
142
+
143
+ check_part_limits
142
144
  end
143
145
 
144
146
  def on_mime_body mime_index, content
@@ -150,13 +152,23 @@ module Rack
150
152
 
151
153
  private
152
154
 
153
- def check_open_files
154
- if Utils.multipart_part_limit > 0
155
- if @open_files >= Utils.multipart_part_limit
155
+ def check_part_limits
156
+ file_limit = Utils.multipart_file_limit
157
+ part_limit = Utils.multipart_total_part_limit
158
+
159
+ if file_limit && file_limit > 0
160
+ if @open_files >= file_limit
156
161
  @mime_parts.each(&:close)
157
162
  raise MultipartPartLimitError, 'Maximum file multiparts in content reached'
158
163
  end
159
164
  end
165
+
166
+ if part_limit && part_limit > 0
167
+ if @mime_parts.size >= part_limit
168
+ @mime_parts.each(&:close)
169
+ raise MultipartTotalPartLimitError, 'Maximum total multiparts in content reached'
170
+ end
171
+ end
160
172
  end
161
173
  end
162
174
 
@@ -302,8 +314,9 @@ module Rack
302
314
  elsif filename = params['filename*']
303
315
  encoding, _, filename = filename.split("'", 3)
304
316
  end
305
- when BROKEN_QUOTED, BROKEN_UNQUOTED
317
+ when BROKEN
306
318
  filename = $1
319
+ filename = $1 if filename =~ /^"(.*)"$/
307
320
  end
308
321
 
309
322
  return unless filename
@@ -14,13 +14,12 @@ module Rack
14
14
  TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
15
15
  CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
16
16
  VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
17
- BROKEN_QUOTED = /^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
18
- BROKEN_UNQUOTED = /^#{CONDISP}.*;\sfilename=(#{TOKEN})/i
17
+ BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i
19
18
  MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
20
- MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*\s+name=(#{VALUE})/ni
19
+ MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:[^:]*;\s+name=(#{VALUE})/ni
21
20
  MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
22
21
  # Updated definitions from RFC 2231
23
- ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]}
22
+ ATTRIBUTE_CHAR = %r{[^ \x00-\x1f\x7f)(><@,;:\\"/\[\]?='*%]}
24
23
  ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/
25
24
  SECTION = /\*[0-9]+/
26
25
  REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/
data/lib/rack/utils.rb CHANGED
@@ -53,13 +53,24 @@ module Rack
53
53
  module_function :unescape
54
54
 
55
55
  class << self
56
- attr_accessor :multipart_part_limit
56
+ attr_accessor :multipart_total_part_limit
57
+
58
+ attr_accessor :multipart_file_limit
59
+
60
+ # multipart_part_limit is the original name of multipart_file_limit, but
61
+ # the limit only counts parts with filenames.
62
+ alias multipart_part_limit multipart_file_limit
63
+ alias multipart_part_limit= multipart_file_limit=
57
64
  end
58
65
 
59
- # The maximum number of parts a request can contain. Accepting too many part
60
- # can lead to the server running out of file handles.
66
+ # The maximum number of file parts a request can contain. Accepting too
67
+ # many parts can lead to the server running out of file handles.
61
68
  # Set to `0` for no limit.
62
- self.multipart_part_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || 128).to_i
69
+ self.multipart_file_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_FILE_LIMIT'] || 128).to_i
70
+
71
+ # The maximum total number of parts a request can contain. Accepting too
72
+ # many can lead to excessive memory use and parsing time.
73
+ self.multipart_total_part_limit = (ENV['RACK_MULTIPART_TOTAL_PART_LIMIT'] || 4096).to_i
63
74
 
64
75
  def self.param_depth_limit
65
76
  default_query_parser.param_depth_limit
@@ -129,8 +140,8 @@ module Rack
129
140
  module_function :build_nested_query
130
141
 
131
142
  def q_values(q_value_header)
132
- q_value_header.to_s.split(/\s*,\s*/).map do |part|
133
- value, parameters = part.split(/\s*;\s*/, 2)
143
+ q_value_header.to_s.split(',').map do |part|
144
+ value, parameters = part.split(';', 2).map(&:strip)
134
145
  quality = 1.0
135
146
  if md = /\Aq=([\d.]+)/.match(parameters)
136
147
  quality = md[1].to_f
@@ -365,17 +376,18 @@ module Rack
365
376
  return nil unless http_range && http_range =~ /bytes=([^;]+)/
366
377
  ranges = []
367
378
  $1.split(/,\s*/).each do |range_spec|
368
- return nil unless range_spec =~ /(\d*)-(\d*)/
369
- r0,r1 = $1, $2
370
- if r0.empty?
371
- return nil if r1.empty?
379
+ return nil unless range_spec.include?('-')
380
+ range = range_spec.split('-')
381
+ r0, r1 = range[0], range[1]
382
+ if r0.nil? || r0.empty?
383
+ return nil if r1.nil?
372
384
  # suffix-byte-range-spec, represents trailing suffix of file
373
385
  r0 = size - r1.to_i
374
386
  r0 = 0 if r0 < 0
375
387
  r1 = size - 1
376
388
  else
377
389
  r0 = r0.to_i
378
- if r1.empty?
390
+ if r1.nil?
379
391
  r1 = size - 1
380
392
  else
381
393
  r1 = r1.to_i
data/lib/rack.rb CHANGED
@@ -18,7 +18,7 @@ module Rack
18
18
  VERSION.join(".")
19
19
  end
20
20
 
21
- RELEASE = "2.0.9"
21
+ RELEASE = "2.0.9.4"
22
22
 
23
23
  # Return the Rack release as a dotted string.
24
24
  def self.release
data/test/cgi/test.gz CHANGED
File without changes
@@ -1,6 +1,6 @@
1
1
  --AaB03x
2
2
  Content-Type: image/jpeg
3
- Content-Disposition: attachment; name="files"; filename=""human" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500";
3
+ Content-Disposition: attachment; name="files"; filename="\"human\" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500";
4
4
  Content-Description: a complete map of the human genome
5
5
 
6
6
  contents
@@ -21,6 +21,10 @@ describe Rack::CommonLogger do
21
21
  [200,
22
22
  {"Content-Type" => "text/html", "Content-Length" => "0"},
23
23
  []]}
24
+ app_without_lint = lambda { |env|
25
+ [200,
26
+ { "content-type" => "text/html", "content-length" => length.to_s },
27
+ [obj]]}
24
28
 
25
29
  it "log to rack.errors by default" do
26
30
  res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
@@ -85,6 +89,14 @@ describe Rack::CommonLogger do
85
89
  (0..1).must_include duration.to_f
86
90
  end
87
91
 
92
+ it "escapes non printable characters except newline" do
93
+ logdev = StringIO.new
94
+ log = Logger.new(logdev)
95
+ Rack::MockRequest.new(Rack::CommonLogger.new(app_without_lint, log)).request("GET\b", "/hello")
96
+
97
+ logdev.string.must_match(/GET\\x8 \/hello/)
98
+ end
99
+
88
100
  def length
89
101
  123
90
102
  end
data/test/spec_lint.rb CHANGED
@@ -96,6 +96,11 @@ describe Rack::Lint do
96
96
  }.must_raise(Rack::Lint::LintError).
97
97
  message.must_match(/REQUEST_METHOD/)
98
98
 
99
+ lambda {
100
+ Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "OOPS?\b!"))
101
+ }.must_raise(Rack::Lint::LintError).
102
+ message.must_match(/OOPS\?\\/)
103
+
99
104
  lambda {
100
105
  Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy"))
101
106
  }.must_raise(Rack::Lint::LintError).
@@ -381,19 +381,6 @@ describe Rack::Multipart do
381
381
  params["files"][:tempfile].read.must_equal "contents"
382
382
  end
383
383
 
384
- it "parse filename with unescaped quotes" do
385
- env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_quotes))
386
- params = Rack::Multipart.parse_multipart(env)
387
- params["files"][:type].must_equal "application/octet-stream"
388
- params["files"][:filename].must_equal "escape \"quotes"
389
- params["files"][:head].must_equal "Content-Disposition: form-data; " +
390
- "name=\"files\"; " +
391
- "filename=\"escape \"quotes\"\r\n" +
392
- "Content-Type: application/octet-stream\r\n"
393
- params["files"][:name].must_equal "files"
394
- params["files"][:tempfile].read.must_equal "contents"
395
- end
396
-
397
384
  it "parse filename with escaped quotes and modification param" do
398
385
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes_and_modification_param))
399
386
  params = Rack::Multipart.parse_multipart(env)
@@ -402,7 +389,7 @@ describe Rack::Multipart do
402
389
  params["files"][:head].must_equal "Content-Type: image/jpeg\r\n" +
403
390
  "Content-Disposition: attachment; " +
404
391
  "name=\"files\"; " +
405
- "filename=\"\"human\" genome.jpeg\"; " +
392
+ "filename=\"\\\"human\\\" genome.jpeg\"; " +
406
393
  "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" +
407
394
  "Content-Description: a complete map of the human genome\r\n"
408
395
  params["files"][:name].must_equal "files"
@@ -561,6 +548,18 @@ Content-Type: image/jpeg\r
561
548
  end
562
549
  end
563
550
 
551
+ it "reach a multipart total limit" do
552
+ begin
553
+ previous_limit = Rack::Utils.multipart_total_part_limit
554
+ Rack::Utils.multipart_total_part_limit = 5
555
+
556
+ env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields)
557
+ lambda { Rack::Multipart.parse_multipart(env) }.must_raise Rack::Multipart::MultipartTotalPartLimitError
558
+ ensure
559
+ Rack::Utils.multipart_total_part_limit = previous_limit
560
+ end
561
+ end
562
+
564
563
  it "return nil if no UploadedFiles were used" do
565
564
  data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
566
565
  data.must_be_nil
data/test/spec_request.rb CHANGED
@@ -911,7 +911,7 @@ EOF
911
911
  f[:tempfile].size.must_equal 76
912
912
  end
913
913
 
914
- it "MultipartPartLimitError when request has too many multipart parts if limit set" do
914
+ it "MultipartPartLimitError when request has too many multipart file parts if limit set" do
915
915
  begin
916
916
  data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
917
917
  data += "--AaB03x--\r"
@@ -927,6 +927,22 @@ EOF
927
927
  end
928
928
  end
929
929
 
930
+ it "MultipartPartLimitError when request has too many multipart total parts if limit set" do
931
+ begin
932
+ data = 10000.times.map { "--AaB03x\r\ncontent-type: text/plain\r\ncontent-disposition: attachment; name=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
933
+ data += "--AaB03x--\r"
934
+
935
+ options = {
936
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
937
+ "CONTENT_LENGTH" => data.length.to_s,
938
+ :input => StringIO.new(data)
939
+ }
940
+
941
+ request = make_request Rack::MockRequest.env_for("/", options)
942
+ lambda { request.POST }.must_raise Rack::Multipart::MultipartTotalPartLimitError
943
+ end
944
+ end
945
+
930
946
  it 'closes tempfiles it created in the case of too many created' do
931
947
  begin
932
948
  data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.9
4
+ version: 2.0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leah Neukirchen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-08 00:00:00.000000000 Z
11
+ date: 2024-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -260,7 +260,7 @@ homepage: https://rack.github.io/
260
260
  licenses:
261
261
  - MIT
262
262
  metadata: {}
263
- post_install_message:
263
+ post_install_message:
264
264
  rdoc_options: []
265
265
  require_paths:
266
266
  - lib
@@ -275,60 +275,60 @@ required_rubygems_version: !ruby/object:Gem::Requirement
275
275
  - !ruby/object:Gem::Version
276
276
  version: '0'
277
277
  requirements: []
278
- rubygems_version: 3.1.2
279
- signing_key:
278
+ rubygems_version: 3.4.10
279
+ signing_key:
280
280
  specification_version: 4
281
281
  summary: a modular Ruby webserver interface
282
282
  test_files:
283
- - test/spec_multipart.rb
283
+ - test/spec_auth_basic.rb
284
+ - test/spec_auth_digest.rb
285
+ - test/spec_body_proxy.rb
286
+ - test/spec_builder.rb
287
+ - test/spec_cascade.rb
288
+ - test/spec_cgi.rb
289
+ - test/spec_chunked.rb
290
+ - test/spec_common_logger.rb
291
+ - test/spec_conditional_get.rb
292
+ - test/spec_config.rb
293
+ - test/spec_content_length.rb
294
+ - test/spec_content_type.rb
284
295
  - test/spec_deflater.rb
285
- - test/spec_static.rb
286
- - test/spec_session_cookie.rb
287
- - test/spec_session_pool.rb
296
+ - test/spec_directory.rb
288
297
  - test/spec_etag.rb
289
- - test/spec_version.rb
298
+ - test/spec_events.rb
299
+ - test/spec_fastcgi.rb
300
+ - test/spec_file.rb
290
301
  - test/spec_handler.rb
291
- - test/spec_thin.rb
292
- - test/spec_session_abstract_id.rb
293
- - test/spec_mime.rb
294
- - test/spec_recursive.rb
295
- - test/spec_null_logger.rb
302
+ - test/spec_head.rb
303
+ - test/spec_lint.rb
304
+ - test/spec_lobster.rb
305
+ - test/spec_lock.rb
306
+ - test/spec_logger.rb
296
307
  - test/spec_media_type.rb
297
- - test/spec_cgi.rb
298
308
  - test/spec_method_override.rb
299
- - test/spec_content_type.rb
300
- - test/spec_session_abstract_session_hash.rb
309
+ - test/spec_mime.rb
310
+ - test/spec_mock.rb
311
+ - test/spec_multipart.rb
312
+ - test/spec_null_logger.rb
313
+ - test/spec_recursive.rb
301
314
  - test/spec_request.rb
302
- - test/spec_chunked.rb
303
- - test/spec_show_exceptions.rb
315
+ - test/spec_response.rb
316
+ - test/spec_rewindable_input.rb
304
317
  - test/spec_runtime.rb
305
- - test/spec_session_persisted_secure_secure_session_hash.rb
306
- - test/spec_fastcgi.rb
307
- - test/spec_common_logger.rb
308
- - test/spec_builder.rb
309
- - test/spec_config.rb
310
- - test/spec_utils.rb
311
318
  - test/spec_sendfile.rb
312
- - test/spec_lobster.rb
313
- - test/spec_lint.rb
314
- - test/spec_conditional_get.rb
315
- - test/spec_tempfile_reaper.rb
316
- - test/spec_mock.rb
317
319
  - test/spec_server.rb
318
- - test/spec_directory.rb
319
- - test/spec_webrick.rb
320
- - test/spec_response.rb
321
- - test/spec_file.rb
320
+ - test/spec_session_abstract_id.rb
321
+ - test/spec_session_abstract_session_hash.rb
322
+ - test/spec_session_cookie.rb
323
+ - test/spec_session_memcache.rb
324
+ - test/spec_session_persisted_secure_secure_session_hash.rb
325
+ - test/spec_session_pool.rb
326
+ - test/spec_show_exceptions.rb
322
327
  - test/spec_show_status.rb
323
- - test/spec_body_proxy.rb
324
- - test/spec_logger.rb
325
- - test/spec_auth_digest.rb
328
+ - test/spec_static.rb
329
+ - test/spec_tempfile_reaper.rb
330
+ - test/spec_thin.rb
326
331
  - test/spec_urlmap.rb
327
- - test/spec_events.rb
328
- - test/spec_cascade.rb
329
- - test/spec_auth_basic.rb
330
- - test/spec_head.rb
331
- - test/spec_lock.rb
332
- - test/spec_rewindable_input.rb
333
- - test/spec_session_memcache.rb
334
- - test/spec_content_length.rb
332
+ - test/spec_utils.rb
333
+ - test/spec_version.rb
334
+ - test/spec_webrick.rb