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/