Skip to content

Commit f92e056

Browse files
authored
Only treat space and \t as allowed whitespace in headers
RFC 7230 (HTTP RFC) Section 3.2.3 is clear that those are the only two allowed characters for required/optional whitespace in headers. RFC 2046 (MIME/Multipart RFC) refers to RFC 822, and RFC 822 Section 3.3 also specifies that linear white space is made up of only space and tab characters. While here, I noticed the content-type parser in the multipart code was requiring a space, when whitespace is optional. Make the whitespace optional, and adjust a test where a content-type was ignored because it didn't use whitespace. The request and utils changes here are operating on header values, and generally other whitespace is allowed there, but I'm not sure we should split on whitespace other than space and \t, so I made the change there as well. There are a lot of places in Rack where we are using strip/strip! were we should potentially change to be more strict and only strip space and \t, but this commit does not attempt to address strip/strip! usage.
1 parent 4af2d21 commit f92e056

File tree

4 files changed

+5
-5
lines changed

4 files changed

+5
-5
lines changed

lib/rack/multipart/parser.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ class BoundaryTooLongError < StandardError
3232

3333
EOL = "\r\n"
3434
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
35-
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
35+
MULTIPART_CONTENT_TYPE = /Content-Type:[ \t]*(.*)#{EOL}/ni
3636
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:(.*)(?=#{EOL}(\S|\z))/ni
37-
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
37+
MULTIPART_CONTENT_ID = /Content-ID:[ \t]*([^#{EOL}]*)/ni
3838

3939
class Parser
4040
BUFSIZE = 1_048_576

lib/rack/request.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ def expand_param_pairs(pairs, query_parser = query_parser())
661661
end
662662

663663
def split_header(value)
664-
value ? value.strip.split(/[,\s]+/) : []
664+
value ? value.strip.split(/[, \t]+/) : []
665665
end
666666

667667
# ipv6 extracted from resolv stdlib, simplified

lib/rack/utils.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ def get_byte_ranges(http_range, size)
408408
return nil if size.zero?
409409
return nil unless http_range && http_range =~ /bytes=([^;]+)/
410410
ranges = []
411-
$1.split(/,\s*/).each do |range_spec|
411+
$1.split(/,[ \t]*/).each do |range_spec|
412412
return nil unless range_spec.include?('-')
413413
range = range_spec.split('-')
414414
r0, r1 = range[0], range[1]

test/spec_multipart.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ def rd.rewind; end
340340

341341
it "ignores content-disposition values over to 1536 bytes" do
342342
x = content_disposition_parse.call("a=#{'a'*1510}; filename=\"bar\"; name=\"file\"")
343-
x.must_equal "text/plain"=>[""]
343+
x.must_equal "application/pdf"=>[""]
344344
end
345345

346346
it 'raises an EOF error on content-length mismatch' do

0 commit comments

Comments
 (0)