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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/rack/constants.rb +0 -2
- data/lib/rack/multipart.rb +0 -25
- data/lib/rack/query_parser.rb +17 -44
- data/lib/rack/request.rb +20 -63
- data/lib/rack/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d78a46e82a591436bcb6103319864e8f4148e56de71e1fc18d3e7c8b2e97751
|
4
|
+
data.tar.gz: bbc8b98ab7d2a4c80876e840fe04d20e99b973d274ae5366544154a5cacba4df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/rack/constants.rb
CHANGED
@@ -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
|
data/lib/rack/multipart.rb
CHANGED
@@ -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]
|
data/lib/rack/query_parser.rb
CHANGED
@@ -39,42 +39,19 @@ module Rack
|
|
39
39
|
@param_depth_limit = param_depth_limit
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
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
|
-
|
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
|
-
|
101
|
-
|
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
|
-
|
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
|
-
|
499
|
-
set_header
|
500
|
-
set_header
|
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
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
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
|
-
|
516
|
+
set_header RACK_REQUEST_FORM_INPUT, nil
|
517
|
+
set_header(RACK_REQUEST_FORM_HASH, {})
|
539
518
|
elsif form_data? || parseable_data?
|
540
|
-
unless
|
541
|
-
form_vars =
|
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
|
-
|
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
|
-
|
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
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.
|
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-
|
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.
|
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: []
|