@@ -29,6 +29,18 @@ def multipart_file(name)
2929 File . join ( File . dirname ( __FILE__ ) , "multipart" , name . to_s )
3030 end
3131
32+ def with_multipart_limit ( limit )
33+ previous = Rack ::Multipart ::Parser . send ( :const_get , :PARSER_BYTESIZE_LIMIT )
34+ begin
35+ Rack ::Multipart ::Parser . send ( :remove_const , :PARSER_BYTESIZE_LIMIT )
36+ Rack ::Multipart ::Parser . const_set ( :PARSER_BYTESIZE_LIMIT , limit )
37+ yield
38+ ensure
39+ Rack ::Multipart ::Parser . send ( :remove_const , :PARSER_BYTESIZE_LIMIT )
40+ Rack ::Multipart ::Parser . const_set ( :PARSER_BYTESIZE_LIMIT , previous )
41+ end
42+ end
43+
3244 it "returns nil if the content type is not multipart" do
3345 env = Rack ::MockRequest . env_for ( "/" , "CONTENT_TYPE" => 'application/x-www-form-urlencoded' , :input => "" )
3446 Rack ::Multipart . parse_multipart ( env ) . must_be_nil
@@ -64,6 +76,49 @@ def multipart_file(name)
6476 } . must_raise Rack ::Multipart ::Error
6577 end
6678
79+ it "raises an exception if Content-Length exceeds total bytesize limit" do
80+ with_multipart_limit ( 1024 ) do
81+ env = Rack ::MockRequest . env_for ( "/" ,
82+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x" ,
83+ "CONTENT_LENGTH" => "2048" ,
84+ :input => StringIO . new ( "--AaB03x--\r \n " ) )
85+
86+ lambda {
87+ Rack ::Multipart . parse_multipart ( env )
88+ } . must_raise ( Rack ::Multipart ::Error )
89+ end
90+ end
91+
92+ it "allows requests within the total bytesize limit" do
93+ with_multipart_limit ( 1024 * 1024 ) do
94+ env = Rack ::MockRequest . env_for ( "/" , multipart_fixture ( :text ) )
95+ params = Rack ::Multipart . parse_multipart ( env )
96+ params [ "submit-name" ] . must_equal "Larry"
97+ end
98+ end
99+
100+ it "skips total bytesize check when there is no limit" do
101+ with_multipart_limit ( nil ) do
102+ env = Rack ::MockRequest . env_for ( "/" , multipart_fixture ( :text ) )
103+ params = Rack ::Multipart . parse_multipart ( env )
104+ params [ "submit-name" ] . must_equal "Larry"
105+ end
106+ end
107+
108+ it "enforces total bytesize limit during streaming when Content-Length is absent" do
109+ with_multipart_limit ( 1 ) do
110+ # Even without Content-Length, the streaming check catches oversized uploads
111+ fixture = multipart_fixture ( :text )
112+ fixture . delete ( "CONTENT_LENGTH" )
113+ env = Rack ::MockRequest . env_for ( "/" , fixture )
114+ env . delete ( "CONTENT_LENGTH" )
115+
116+ lambda {
117+ Rack ::Multipart . parse_multipart ( env )
118+ } . must_raise Rack ::Multipart ::Error
119+ end
120+ end
121+
67122 it "raises a bad request exception if no body is given but content type indicates a multipart body" do
68123 env = Rack ::MockRequest . env_for ( "/" , "CONTENT_TYPE" => 'multipart/form-data; boundary=BurgerBurger' , :input => nil )
69124 lambda {
0 commit comments