summary refs log tree commit
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-05-25 11:07:17 -0700
committerJeremy Evans <code@jeremyevans.net>2022-05-25 12:52:44 -0700
commitd866dc42f5d886d94b91eacba9f7da8ba72e66ce (patch)
treebac515974ff98782e0df9f68494479475d7c8c0e
parent7605ec326c342d444ec0c9eb77dcb5a08739e9e2 (diff)
downloadrack-d866dc42f5d886d94b91eacba9f7da8ba72e66ce.tar.gz
Impose a 70 character limit on boundary size
This limit comes from RFC 1521 Section 7.2.1.  Clients generally
do not use boundaries longer than 55 characters.
-rw-r--r--lib/rack/multipart/parser.rb10
-rw-r--r--test/spec_multipart.rb7
2 files changed, 17 insertions, 0 deletions
diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb
index 8e770ecf..6fcfd487 100644
--- a/lib/rack/multipart/parser.rb
+++ b/lib/rack/multipart/parser.rb
@@ -12,6 +12,10 @@ module Rack
     # that ends early.
     class EmptyContentError < ::EOFError; end
 
+    # Base class for multipart exceptions that do not subclass from
+    # other exception classes for backwards compatibility.
+    class Error < StandardError; end
+
     EOL = "\r\n"
     MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
     TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
@@ -92,6 +96,12 @@ module Rack
         boundary = parse_boundary content_type
         return EMPTY unless boundary
 
+        if boundary.length > 70
+          # RFC 1521 Section 7.2.1 imposes a 70 character maximum for the boundary.
+          # Most clients use no more than 55 characters.
+          raise Error, "multipart boundary size too large (#{boundary.length} characters)"
+        end
+
         io = BoundedIO.new(io, content_length) if content_length
 
         parser = new(boundary, tmpfile, bufsize, qp)
diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb
index 12065aa1..d921a4b9 100644
--- a/test/spec_multipart.rb
+++ b/test/spec_multipart.rb
@@ -35,6 +35,13 @@ describe Rack::Multipart do
     Rack::Multipart.parse_multipart(env).must_be_nil
   end
 
+  it "raises exception if boundary is too long" do
+    env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename, "A"*71))
+    lambda {
+      Rack::Multipart.parse_multipart(env)
+    }.must_raise Rack::Multipart::Error
+  end
+
   it "parse multipart content when content type present but disposition is not" do
     env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_disposition))
     params = Rack::Multipart.parse_multipart(env)