diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb index 2469459d7..345cc258b 100644 --- a/lib/rack/multipart/parser.rb +++ b/lib/rack/multipart/parser.rb @@ -213,6 +213,7 @@ def initialize(boundary, tempfile, bufsize, query_parser) @sbuf = StringScanner.new("".dup) @body_regex = /(?:#{EOL}|\A)--#{Regexp.quote(boundary)}(?:#{EOL}|--)/m + @end_boundary_size = boundary.bytesize + 4 # (-- at start, -- at finish) @rx_max_size = boundary.bytesize + 6 # (\r\n-- at start, either \r\n or -- at finish) @head_regex = /(.*?#{EOL})#{EOL}/m end @@ -279,7 +280,14 @@ def handle_fast_forward @state = :MIME_HEAD return when :END_BOUNDARY - # invalid multipart upload, but retry for opening boundary + # invalid multipart upload + if @sbuf.pos == @end_boundary_size && @sbuf.rest == EOL + # stop parsing a buffer if a buffer is only an end boundary. + @state = :DONE + return + end + + # retry for opening boundary else # no boundary found, keep reading data return :want_read diff --git a/test/spec_request.rb b/test/spec_request.rb index 169118635..c22619063 100644 --- a/test/spec_request.rb +++ b/test/spec_request.rb @@ -1333,6 +1333,24 @@ def initialize(*) f[:tempfile].size.must_equal 76 end + it "parse multipart delimiter-only boundary" do + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input + ) + + req = make_request mr + req.query_string.must_equal "" + req.GET.must_be :empty? + req.POST.must_be :empty? + req.params.must_equal({}) + end + it "MultipartPartLimitError when request has too many multipart file parts if limit set" do begin 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")