rack 3.0.6.1 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.

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: b43a4c41d97b3e6b9790b04c0713ac20814fa986310ccd17918baaaf3f94b260
4
- data.tar.gz: a461e437f8cf4591d39d4a84fdceec6ffddb3d11c67fc5a4bdf74926e18d80bc
3
+ metadata.gz: 6d78a46e82a591436bcb6103319864e8f4148e56de71e1fc18d3e7c8b2e97751
4
+ data.tar.gz: bbc8b98ab7d2a4c80876e840fe04d20e99b973d274ae5366544154a5cacba4df
5
5
  SHA512:
6
- metadata.gz: cb7fcf3c2fa1cd168ff0373246160eec7fa6d94a6b4e5d88438f2239cf79e8b9df708626b32603f63368c1133ca7b3fb00d16a292ca5214a7740c558201c1a0f
7
- data.tar.gz: 64d3a5fb0603f6f12760bd2ff95a118985eb843b1875d36c9f9f2af37ca413f311e3c566f5861efb159349d9958ef2c78f8d537ba618009d0ca3ac91047d6d53
6
+ metadata.gz: 699070faa7af77eb112f78684073725f304d17604afbd6fec37316ad020903f148ade1c070458999d526d4d49077f47abafca5c1ce1e4d7c12ef7a9bdb4fce5d
7
+ data.tar.gz: 8e0573a8dc26d426a3fd7b2f770b343cb1ea1c1e57f51261a7c8af745bf5d37c5bb637d4a6170a9e904a1dcb8a69b909a6f8c4bb8dae8791800b88cf7d06fd64
data/CHANGELOG.md CHANGED
@@ -2,10 +2,22 @@
2
2
 
3
3
  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/).
4
4
 
5
+ ## [3.0.7] - 2023-03-16
6
+
7
+ - Make query parameters without `=` have `nil` values. ([#2059](https://github.com/rack/rack/pull/2059), [@jeremyevans])
8
+
5
9
  ## [3.0.6.1] - 2023-03-13
6
10
 
7
11
  - [CVE-2023-27539] Avoid ReDoS in header parsing
8
12
 
13
+ ## [3.0.6] - 2023-03-13
14
+
15
+ - Add `QueryParser#missing_value` for handling missing values + tests. ([#2052](https://github.com/rack/rack/pull/2052), [@ioquatix])
16
+
17
+ ## [3.0.5] - 2023-03-13
18
+
19
+ - Split form/query parsing into two steps. ([#2038](https://github.com/rack/rack/pull/2038), [@matthewd](https://github.com/matthewd))
20
+
9
21
  ## [3.0.4.1] - 2023-03-02
10
22
 
11
23
  - [CVE-2023-27530] Introduce multipart_total_part_limit to limit total parts
@@ -54,13 +54,11 @@ module Rack
54
54
  RACK_RESPONSE_FINISHED = 'rack.response_finished'
55
55
  RACK_REQUEST_FORM_INPUT = 'rack.request.form_input'
56
56
  RACK_REQUEST_FORM_HASH = 'rack.request.form_hash'
57
- RACK_REQUEST_FORM_PAIRS = 'rack.request.form_pairs'
58
57
  RACK_REQUEST_FORM_VARS = 'rack.request.form_vars'
59
58
  RACK_REQUEST_FORM_ERROR = 'rack.request.form_error'
60
59
  RACK_REQUEST_COOKIE_HASH = 'rack.request.cookie_hash'
61
60
  RACK_REQUEST_COOKIE_STRING = 'rack.request.cookie_string'
62
61
  RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'
63
- RACK_REQUEST_QUERY_PAIRS = 'rack.request.query_pairs'
64
62
  RACK_REQUEST_QUERY_STRING = 'rack.request.query_string'
65
63
  RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method'
66
64
  end
@@ -13,31 +13,6 @@ module Rack
13
13
  module Multipart
14
14
  MULTIPART_BOUNDARY = "AaB03x"
15
15
 
16
- # Accumulator for multipart form data, conforming to the QueryParser API.
17
- # In future, the Parser could return the pair list directly, but that would
18
- # change its API.
19
- class ParamList # :nodoc:
20
- def self.make_params
21
- new
22
- end
23
-
24
- def self.normalize_params(params, key, value)
25
- params << [key, value]
26
- end
27
-
28
- def initialize
29
- @pairs = []
30
- end
31
-
32
- def <<(pair)
33
- @pairs << pair
34
- end
35
-
36
- def to_params_hash
37
- @pairs
38
- end
39
- end
40
-
41
16
  class << self
42
17
  def parse_multipart(env, params = Rack::Utils.default_query_parser)
43
18
  io = env[RACK_INPUT]
@@ -39,42 +39,19 @@ module Rack
39
39
  @param_depth_limit = param_depth_limit
40
40
  end
41
41
 
42
- # Originally stolen from Mongrel, now with some modifications:
42
+ # Stolen from Mongrel, with some small modifications:
43
43
  # Parses a query string by breaking it up at the '&'. You can also use this
44
44
  # to parse cookies by changing the characters used in the second parameter
45
45
  # (which defaults to '&').
46
- #
47
- # Returns an array of 2-element arrays, where the first element is the
48
- # key and the second element is the value.
49
- def split_query(qs, separator = nil, &unescaper)
50
- pairs = []
51
-
52
- if qs && !qs.empty?
53
- unescaper ||= method(:unescape)
54
-
55
- qs.split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
56
- next if p.empty?
57
- pair = p.split('=', 2).map!(&unescaper)
58
- pair << nil if pair.length == 1
59
- pairs << pair
60
- end
61
- end
62
-
63
- pairs
64
- rescue ArgumentError => e
65
- raise InvalidParameterError, e.message, e.backtrace
66
- end
67
-
68
- # Parses a query string by breaking it up at the '&'. You can also use this
69
- # to parse cookies by changing the characters used in the second parameter
70
- # (which defaults to '&').
71
- #
72
- # Returns a hash where each value is a string (when a key only appears once)
73
- # or an array of strings (when a key appears more than once).
74
46
  def parse_query(qs, separator = nil, &unescaper)
47
+ unescaper ||= method(:unescape)
48
+
75
49
  params = make_params
76
50
 
77
- split_query(qs, separator, &unescaper).each do |k, v|
51
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
52
+ next if p.empty?
53
+ k, v = p.split('=', 2).map!(&unescaper)
54
+
78
55
  if cur = params[k]
79
56
  if cur.class == Array
80
57
  params[k] << v
@@ -86,7 +63,7 @@ module Rack
86
63
  end
87
64
  end
88
65
 
89
- params.to_h
66
+ return params.to_h
90
67
  end
91
68
 
92
69
  # parse_nested_query expands a query string into structural types. Supported
@@ -97,11 +74,17 @@ module Rack
97
74
  def parse_nested_query(qs, separator = nil)
98
75
  params = make_params
99
76
 
100
- split_query(qs, separator).each do |k, v|
101
- _normalize_params(params, k, v, 0)
77
+ unless qs.nil? || qs.empty?
78
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
79
+ k, v = p.split('=', 2).map! { |s| unescape(s) }
80
+
81
+ _normalize_params(params, k, v, 0)
82
+ end
102
83
  end
103
84
 
104
- params.to_h
85
+ return params.to_h
86
+ rescue ArgumentError => e
87
+ raise InvalidParameterError, e.message, e.backtrace
105
88
  end
106
89
 
107
90
  # normalize_params recursively expands parameters into structural types. If
@@ -113,14 +96,6 @@ module Rack
113
96
  _normalize_params(params, name, v, 0)
114
97
  end
115
98
 
116
- # This value is used by default when a parameter is missing (nil). This
117
- # usually happens when a parameter is specified without an `=value` part.
118
- # The default value is an empty string, but this can be overridden by
119
- # subclasses.
120
- def missing_value
121
- String.new
122
- end
123
-
124
99
  private def _normalize_params(params, name, v, depth)
125
100
  raise ParamsTooDeepError if depth >= param_depth_limit
126
101
 
@@ -155,8 +130,6 @@ module Rack
155
130
 
156
131
  return if k.empty?
157
132
 
158
- v ||= missing_value
159
-
160
133
  if after == ''
161
134
  if k == '[]' && depth != 0
162
135
  return [v]
data/lib/rack/request.rb CHANGED
@@ -483,22 +483,11 @@ module Rack
483
483
  # Returns the data received in the query string.
484
484
  def GET
485
485
  if get_header(RACK_REQUEST_QUERY_STRING) == query_string
486
- if query_hash = get_header(RACK_REQUEST_QUERY_HASH)
487
- return query_hash
488
- end
489
- end
490
-
491
- set_header(RACK_REQUEST_QUERY_HASH, expand_params(query_param_list))
492
- end
493
-
494
- def query_param_list
495
- if get_header(RACK_REQUEST_QUERY_STRING) == query_string
496
- get_header(RACK_REQUEST_QUERY_PAIRS)
486
+ get_header(RACK_REQUEST_QUERY_HASH)
497
487
  else
498
- query_pairs = split_query(query_string, '&')
499
- set_header RACK_REQUEST_QUERY_STRING, query_string
500
- set_header RACK_REQUEST_QUERY_HASH, nil
501
- set_header(RACK_REQUEST_QUERY_PAIRS, query_pairs)
488
+ query_hash = parse_query(query_string, '&')
489
+ set_header(RACK_REQUEST_QUERY_STRING, query_string)
490
+ set_header(RACK_REQUEST_QUERY_HASH, query_hash)
502
491
  end
503
492
  end
504
493
 
@@ -507,16 +496,6 @@ module Rack
507
496
  # This method support both application/x-www-form-urlencoded and
508
497
  # multipart/form-data.
509
498
  def POST
510
- if get_header(RACK_REQUEST_FORM_INPUT).equal?(get_header(RACK_INPUT))
511
- if form_hash = get_header(RACK_REQUEST_FORM_HASH)
512
- return form_hash
513
- end
514
- end
515
-
516
- set_header(RACK_REQUEST_FORM_HASH, expand_params(body_param_list))
517
- end
518
-
519
- def body_param_list
520
499
  if error = get_header(RACK_REQUEST_FORM_ERROR)
521
500
  raise error.class, error.message, cause: error.cause
522
501
  end
@@ -524,36 +503,36 @@ module Rack
524
503
  begin
525
504
  rack_input = get_header(RACK_INPUT)
526
505
 
527
- form_pairs = nil
528
-
529
- # If the form data has already been memoized from the same
530
- # input:
531
- if get_header(RACK_REQUEST_FORM_INPUT).equal?(rack_input)
532
- if form_pairs = get_header(RACK_REQUEST_FORM_PAIRS)
533
- return form_pairs
506
+ # If the form hash was already memoized:
507
+ if form_hash = get_header(RACK_REQUEST_FORM_HASH)
508
+ # And it was memoized from the same input:
509
+ if get_header(RACK_REQUEST_FORM_INPUT).equal?(rack_input)
510
+ return form_hash
534
511
  end
535
512
  end
536
513
 
514
+ # Otherwise, figure out how to parse the input:
537
515
  if rack_input.nil?
538
- form_pairs = []
516
+ set_header RACK_REQUEST_FORM_INPUT, nil
517
+ set_header(RACK_REQUEST_FORM_HASH, {})
539
518
  elsif form_data? || parseable_data?
540
- unless form_pairs = Rack::Multipart.extract_multipart(self, Rack::Multipart::ParamList)
541
- form_vars = rack_input.read
519
+ unless set_header(RACK_REQUEST_FORM_HASH, parse_multipart)
520
+ form_vars = get_header(RACK_INPUT).read
542
521
 
543
522
  # Fix for Safari Ajax postings that always append \0
544
523
  # form_vars.sub!(/\0\z/, '') # performance replacement:
545
524
  form_vars.slice!(-1) if form_vars.end_with?("\0")
546
525
 
547
526
  set_header RACK_REQUEST_FORM_VARS, form_vars
548
- form_pairs = split_query(form_vars, '&')
527
+ set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')
549
528
  end
529
+
530
+ set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
531
+ get_header RACK_REQUEST_FORM_HASH
550
532
  else
551
- form_pairs = []
533
+ set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
534
+ set_header(RACK_REQUEST_FORM_HASH, {})
552
535
  end
553
-
554
- set_header RACK_REQUEST_FORM_INPUT, rack_input
555
- set_header RACK_REQUEST_FORM_HASH, nil
556
- set_header(RACK_REQUEST_FORM_PAIRS, form_pairs)
557
536
  rescue => error
558
537
  set_header(RACK_REQUEST_FORM_ERROR, error)
559
538
  raise
@@ -693,28 +672,6 @@ module Rack
693
672
  Rack::Multipart.extract_multipart(self, query_parser)
694
673
  end
695
674
 
696
- def split_query(query, d = '&')
697
- query_parser = query_parser()
698
- unless query_parser.respond_to?(:split_query)
699
- query_parser = Utils.default_query_parser
700
- unless query_parser.respond_to?(:split_query)
701
- query_parser = QueryParser.make_default(0)
702
- end
703
- end
704
-
705
- query_parser.split_query(query, d)
706
- end
707
-
708
- def expand_params(pairs, query_parser = query_parser())
709
- params = query_parser.make_params
710
-
711
- pairs.each do |key, value|
712
- query_parser.normalize_params(params, key, value)
713
- end
714
-
715
- params.to_params_hash
716
- end
717
-
718
675
  def split_header(value)
719
676
  value ? value.strip.split(/[,\s]+/) : []
720
677
  end
data/lib/rack/version.rb CHANGED
@@ -25,7 +25,7 @@ module Rack
25
25
  VERSION
26
26
  end
27
27
 
28
- RELEASE = "3.0.6.1"
28
+ RELEASE = "3.0.7"
29
29
 
30
30
  # Return the Rack release as a dotted string.
31
31
  def self.release
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: 3.0.6.1
4
+ version: 3.0.7
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: 2023-03-13 00:00:00.000000000 Z
11
+ date: 2023-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -149,7 +149,7 @@ metadata:
149
149
  changelog_uri: https://github.com/rack/rack/blob/main/CHANGELOG.md
150
150
  documentation_uri: https://rubydoc.info/github/rack/rack
151
151
  source_code_uri: https://github.com/rack/rack
152
- post_install_message:
152
+ post_install_message:
153
153
  rdoc_options: []
154
154
  require_paths:
155
155
  - lib
@@ -164,8 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  requirements: []
167
- rubygems_version: 3.0.3.1
168
- signing_key:
167
+ rubygems_version: 3.4.6
168
+ signing_key:
169
169
  specification_version: 4
170
170
  summary: A modular Ruby webserver interface.
171
171
  test_files: []