rack 3.0.4.2 → 3.0.5
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 +1 -1
- data/lib/rack/constants.rb +2 -0
- data/lib/rack/multipart.rb +25 -0
- data/lib/rack/query_parser.rb +34 -17
- data/lib/rack/request.rb +69 -15
- data/lib/rack/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14dbe09610211d4f7ea05476089ae7c5a276f62d267dea6f3902bdfbe8ecab6b
|
4
|
+
data.tar.gz: 12354e0b19330b88a4fe73e5675625b3ae096e6e2db087fc2e8d4167f4c10368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eee29ac6d6b1f61355b1e802fece0f3d4af51603cfd0dca142ed7846f26059467a8cc08143f4dab9bfcb2fa20f93fd67d7654b23c9898b545761de0b1ea57003
|
7
|
+
data.tar.gz: f654a6cb49ed589ec844f930bc8dc0edec5c818665183011215b72c7b3dc7619b1726a2ec6ff045fd1914de85592c2697a8b10b45073744cba98124cc6f19dbb
|
data/CHANGELOG.md
CHANGED
@@ -12,7 +12,7 @@ All notable changes to this project will be documented in this file. For info on
|
|
12
12
|
- [CVE-2022-44570] Fix ReDoS in Rack::Utils.get_byte_ranges
|
13
13
|
- [CVE-2022-44572] Forbid control characters in attributes (also ReDoS)
|
14
14
|
|
15
|
-
## [3.0.4] -
|
15
|
+
## [3.0.4] - 2023-01-17
|
16
16
|
|
17
17
|
- `Rack::Request#POST` should consistently raise errors. Cache errors that occur when invoking `Rack::Request#POST` so they can be raised again later. ([#2010](https://github.com/rack/rack/pull/2010), [@ioquatix])
|
18
18
|
- Fix `Rack::Lint` error message for `HTTP_CONTENT_TYPE` and `HTTP_CONTENT_LENGTH`. ([#2007](https://github.com/rack/rack/pull/2007), [@byroot](https://github.com/byroot))
|
data/lib/rack/constants.rb
CHANGED
@@ -54,11 +54,13 @@ 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'
|
57
58
|
RACK_REQUEST_FORM_VARS = 'rack.request.form_vars'
|
58
59
|
RACK_REQUEST_FORM_ERROR = 'rack.request.form_error'
|
59
60
|
RACK_REQUEST_COOKIE_HASH = 'rack.request.cookie_hash'
|
60
61
|
RACK_REQUEST_COOKIE_STRING = 'rack.request.cookie_string'
|
61
62
|
RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'
|
63
|
+
RACK_REQUEST_QUERY_PAIRS = 'rack.request.query_pairs'
|
62
64
|
RACK_REQUEST_QUERY_STRING = 'rack.request.query_string'
|
63
65
|
RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method'
|
64
66
|
end
|
data/lib/rack/multipart.rb
CHANGED
@@ -13,6 +13,31 @@ 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
|
+
|
16
41
|
class << self
|
17
42
|
def parse_multipart(env, params = Rack::Utils.default_query_parser)
|
18
43
|
io = env[RACK_INPUT]
|
data/lib/rack/query_parser.rb
CHANGED
@@ -37,19 +37,42 @@ module Rack
|
|
37
37
|
@param_depth_limit = param_depth_limit
|
38
38
|
end
|
39
39
|
|
40
|
-
#
|
40
|
+
# Originally stolen from Mongrel, now with some modifications:
|
41
41
|
# Parses a query string by breaking it up at the '&'. You can also use this
|
42
42
|
# to parse cookies by changing the characters used in the second parameter
|
43
43
|
# (which defaults to '&').
|
44
|
-
|
45
|
-
|
44
|
+
#
|
45
|
+
# Returns an array of 2-element arrays, where the first element is the
|
46
|
+
# key and the second element is the value.
|
47
|
+
def split_query(qs, separator = nil, &unescaper)
|
48
|
+
pairs = []
|
49
|
+
|
50
|
+
if qs && !qs.empty?
|
51
|
+
unescaper ||= method(:unescape)
|
52
|
+
|
53
|
+
qs.split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
|
54
|
+
next if p.empty?
|
55
|
+
pair = p.split('=', 2).map!(&unescaper)
|
56
|
+
pair << nil if pair.length == 1
|
57
|
+
pairs << pair
|
58
|
+
end
|
59
|
+
end
|
46
60
|
|
47
|
-
|
61
|
+
pairs
|
62
|
+
rescue ArgumentError => e
|
63
|
+
raise InvalidParameterError, e.message, e.backtrace
|
64
|
+
end
|
48
65
|
|
49
|
-
|
50
|
-
|
51
|
-
|
66
|
+
# Parses a query string by breaking it up at the '&'. You can also use this
|
67
|
+
# to parse cookies by changing the characters used in the second parameter
|
68
|
+
# (which defaults to '&').
|
69
|
+
#
|
70
|
+
# Returns a hash where each value is a string (when a key only appears once)
|
71
|
+
# or an array of strings (when a key appears more than once).
|
72
|
+
def parse_query(qs, separator = nil, &unescaper)
|
73
|
+
params = make_params
|
52
74
|
|
75
|
+
split_query(qs, separator, &unescaper).each do |k, v|
|
53
76
|
if cur = params[k]
|
54
77
|
if cur.class == Array
|
55
78
|
params[k] << v
|
@@ -61,7 +84,7 @@ module Rack
|
|
61
84
|
end
|
62
85
|
end
|
63
86
|
|
64
|
-
|
87
|
+
params.to_h
|
65
88
|
end
|
66
89
|
|
67
90
|
# parse_nested_query expands a query string into structural types. Supported
|
@@ -72,17 +95,11 @@ module Rack
|
|
72
95
|
def parse_nested_query(qs, separator = nil)
|
73
96
|
params = make_params
|
74
97
|
|
75
|
-
|
76
|
-
(
|
77
|
-
k, v = p.split('=', 2).map! { |s| unescape(s) }
|
78
|
-
|
79
|
-
_normalize_params(params, k, v, 0)
|
80
|
-
end
|
98
|
+
split_query(qs, separator).each do |k, v|
|
99
|
+
_normalize_params(params, k, v, 0)
|
81
100
|
end
|
82
101
|
|
83
|
-
|
84
|
-
rescue ArgumentError => e
|
85
|
-
raise InvalidParameterError, e.message, e.backtrace
|
102
|
+
params.to_h
|
86
103
|
end
|
87
104
|
|
88
105
|
# normalize_params recursively expands parameters into structural types. If
|
data/lib/rack/request.rb
CHANGED
@@ -483,11 +483,22 @@ 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
|
-
get_header(RACK_REQUEST_QUERY_HASH)
|
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)
|
487
497
|
else
|
488
|
-
|
489
|
-
set_header
|
490
|
-
set_header
|
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)
|
491
502
|
end
|
492
503
|
end
|
493
504
|
|
@@ -496,32 +507,53 @@ module Rack
|
|
496
507
|
# This method support both application/x-www-form-urlencoded and
|
497
508
|
# multipart/form-data.
|
498
509
|
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
|
499
520
|
if error = get_header(RACK_REQUEST_FORM_ERROR)
|
500
521
|
raise error.class, error.message, cause: error.cause
|
501
522
|
end
|
502
523
|
|
503
524
|
begin
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
525
|
+
rack_input = get_header(RACK_INPUT)
|
526
|
+
|
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
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
if rack_input.nil?
|
538
|
+
form_pairs = []
|
508
539
|
elsif form_data? || parseable_data?
|
509
|
-
unless
|
510
|
-
form_vars =
|
540
|
+
unless form_pairs = Rack::Multipart.extract_multipart(self, Rack::Multipart::ParamList)
|
541
|
+
form_vars = rack_input.read
|
511
542
|
|
512
543
|
# Fix for Safari Ajax postings that always append \0
|
513
544
|
# form_vars.sub!(/\0\z/, '') # performance replacement:
|
514
545
|
form_vars.slice!(-1) if form_vars.end_with?("\0")
|
515
546
|
|
516
547
|
set_header RACK_REQUEST_FORM_VARS, form_vars
|
517
|
-
|
548
|
+
form_pairs = split_query(form_vars, '&')
|
518
549
|
end
|
519
|
-
set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
|
520
|
-
get_header RACK_REQUEST_FORM_HASH
|
521
550
|
else
|
522
|
-
|
523
|
-
set_header(RACK_REQUEST_FORM_HASH, {})
|
551
|
+
form_pairs = []
|
524
552
|
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)
|
525
557
|
rescue => error
|
526
558
|
set_header(RACK_REQUEST_FORM_ERROR, error)
|
527
559
|
raise
|
@@ -661,6 +693,28 @@ module Rack
|
|
661
693
|
Rack::Multipart.extract_multipart(self, query_parser)
|
662
694
|
end
|
663
695
|
|
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
|
+
|
664
718
|
def split_header(value)
|
665
719
|
value ? value.strip.split(/[,\s]+/) : []
|
666
720
|
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.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leah Neukirchen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
164
|
- !ruby/object:Gem::Version
|
165
165
|
version: '0'
|
166
166
|
requirements: []
|
167
|
-
rubygems_version: 3.4.
|
167
|
+
rubygems_version: 3.4.6
|
168
168
|
signing_key:
|
169
169
|
specification_version: 4
|
170
170
|
summary: A modular Ruby webserver interface.
|