@@ -795,6 +795,84 @@ def initialize(*)
795795 req . POST . must_equal "foo" => "bar" , "quux" => "bla"
796796 end
797797
798+ it "limit POST body read to bytesize_limit when parsing url-encoded data" do
799+ # Create a mock input that tracks read calls
800+ reads = [ ]
801+ mock_input = Object . new
802+ mock_input . define_singleton_method ( :read ) do |len = nil |
803+ reads << len
804+ # Return mutable string
805+ "foo=bar" . dup
806+ end
807+
808+ request = make_request \
809+ Rack ::MockRequest . env_for ( "/" ,
810+ 'REQUEST_METHOD' => 'POST' ,
811+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' ,
812+ 'rack.input' => mock_input )
813+
814+ request . POST . must_equal "foo" => "bar"
815+
816+ # Verify read was called with a limit (bytesize_limit + 2), not nil
817+ reads . size . must_equal 1
818+ reads . first . wont_be_nil
819+ reads . first . must_equal ( request . send ( :query_parser ) . bytesize_limit + 2 )
820+ end
821+
822+ it "handle nil return from rack.input.read when parsing url-encoded data" do
823+ # Simulate an input that returns nil on read
824+ mock_input = Object . new
825+ mock_input . define_singleton_method ( :read ) do |len = nil |
826+ nil
827+ end
828+
829+ request = make_request \
830+ Rack ::MockRequest . env_for ( "/" ,
831+ 'REQUEST_METHOD' => 'POST' ,
832+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' ,
833+ 'rack.input' => mock_input )
834+
835+ # Should handle nil gracefully and return empty hash
836+ request . POST . must_equal ( { } )
837+ end
838+
839+ it "truncate POST body at bytesize_limit when parsing url-encoded data" do
840+ # Create input larger than limit
841+ large_body = "a=1&" * 1000000 # Very large body
842+
843+ request = make_request \
844+ Rack ::MockRequest . env_for ( "/" ,
845+ 'REQUEST_METHOD' => 'POST' ,
846+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' ,
847+ :input => large_body )
848+
849+ # Should parse only up to the limit without reading entire body into memory
850+ # The actual parsing may fail due to size limit, which is expected
851+ proc { request . POST } . must_raise Rack ::QueryParser ::QueryLimitError
852+ end
853+
854+ it "clean up Safari's ajax POST body with limited read" do
855+ # Verify Safari null-byte cleanup still works with bounded read
856+ reads = [ ]
857+ mock_input = Object . new
858+ mock_input . define_singleton_method ( :read ) do |len = nil |
859+ reads << len
860+ # Return mutable string (dup ensures it's not frozen)
861+ "foo=bar\0 " . dup
862+ end
863+
864+ request = make_request \
865+ Rack ::MockRequest . env_for ( "/" ,
866+ 'REQUEST_METHOD' => 'POST' ,
867+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' ,
868+ 'rack.input' => mock_input )
869+
870+ request . POST . must_equal "foo" => "bar"
871+
872+ # Verify bounded read was used
873+ reads . first . wont_be_nil
874+ end
875+
798876 it "return form_pairs for url-encoded POST data" do
799877 req = make_request \
800878 Rack ::MockRequest . env_for ( "/" ,
0 commit comments