[前][次][番号順一覧][スレッド一覧]

ruby-changes:50774

From: normal <ko1@a...>
Date: Wed, 28 Mar 2018 17:15:39 +0900 (JST)
Subject: [ruby-changes:50774] normal:r62963 (trunk): webrick/httprequest: use InputBufferSize for chunked requests

normal	2018-03-28 17:06:39 +0900 (Wed, 28 Mar 2018)

  New Revision: 62963

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62963

  Log:
    webrick/httprequest: use InputBufferSize for chunked requests
    
    While WEBrick::HTTPRequest#body provides a Proc interface
    for streaming large request bodies, clients must not force
    the server to use an excessively large chunk size.
    
    * lib/webrick/httprequest.rb (read_chunk_size): limit each
      read and block.call to :InputBufferSize in config.
    * test/webrick/test_httpserver.rb (test_big_chunks): new test

  Modified files:
    trunk/lib/webrick/httprequest.rb
    trunk/test/webrick/test_httpserver.rb
Index: lib/webrick/httprequest.rb
===================================================================
--- lib/webrick/httprequest.rb	(revision 62962)
+++ lib/webrick/httprequest.rb	(revision 62963)
@@ -509,12 +509,16 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/lib/webrick/httprequest.rb#L509
     def read_chunked(socket, block)
       chunk_size, = read_chunk_size(socket)
       while chunk_size > 0
-        data = read_data(socket, chunk_size) # read chunk-data
-        if data.nil? || data.bytesize != chunk_size
-          raise HTTPStatus::BadRequest, "bad chunk data size."
-        end
+        begin
+          sz = [ chunk_size, @buffer_size ].min
+          data = read_data(socket, sz) # read chunk-data
+          if data.nil? || data.bytesize != sz
+            raise HTTPStatus::BadRequest, "bad chunk data size."
+          end
+          block.call(data)
+        end while (chunk_size -= sz) > 0
+
         read_line(socket)                    # skip CRLF
-        block.call(data)
         chunk_size, = read_chunk_size(socket)
       end
       read_header(socket)                    # trailer + CRLF
Index: test/webrick/test_httpserver.rb
===================================================================
--- test/webrick/test_httpserver.rb	(revision 62962)
+++ test/webrick/test_httpserver.rb	(revision 62963)
@@ -475,4 +475,37 @@ class TestWEBrickHTTPServer < Test::Unit https://github.com/ruby/ruby/blob/trunk/test/webrick/test_httpserver.rb#L475
       end
     }
   end
+
+  def test_big_chunks
+    nr_out = 3
+    buf = 'big' # 3 bytes is bigger than 2!
+    config = { :InputBufferSize => 2 }.freeze
+    total = 0
+    all = ''
+    TestWEBrick.start_httpserver(config){|server, addr, port, log|
+      server.mount_proc('/', ->(req, res) {
+        err = []
+        ret = req.body do |chunk|
+          n = chunk.bytesize
+          n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
+          total += n
+          all << chunk
+        end
+        ret.nil? or err << 'req.body should return nil'
+        (buf * nr_out) == all or err << 'input body does not match expected'
+        res.header['connection'] = 'close'
+        res.body = err.join("\n")
+      })
+      TCPSocket.open(addr, port) do |c|
+        c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
+                "Transfer-Encoding: chunked\r\n\r\n")
+        chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
+        nr_out.times { c.write(chunk) }
+        c.write("0\r\n\r\n")
+        head, body = c.read.split("\r\n\r\n")
+        assert_match %r{\AHTTP/1\.1 200 OK}, head
+        assert_nil body
+      end
+    }
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]