-
Notifications
You must be signed in to change notification settings - Fork 105
Description
The contract of readpartial
is that it will return up to the amount requested and no more. However the implementation of readpartial
in WEBrick's HTTPRequest does not honor this contract:
webrick/lib/webrick/httprequest.rb
Lines 276 to 284 in 6b6990e
# for IO.copy_stream. Note: we may return a larger string than +size+ | |
# here; but IO.copy_stream does not care. | |
def readpartial(size, buf = ''.b) # :nodoc | |
res = @body_tmp.shift or raise EOFError, 'end of file reached' | |
buf.replace(res) | |
res.clear | |
@body_rd.resume # get more chunks | |
buf | |
end |
The assumption described here may hold in CRuby, but in JRuby's implementation of copy_stream
we may use an intermediate buffer to hold data on its way, and if readpartial
returns more data than requested we will overflow that buffer. I will be fixing JRuby to raise a more Ruby-friendly error, but it's still going to be an error if we readpartial
N bytes and get N+1.
This is the root cause of a failure in test_big_bodies
from test_httpproxy.rb as described in jruby/jruby#6246. The copy_stream
call deep inside the proxy test fails due to this buffer overflow, which causes the request's piped content to be prematurely closed and the proxy test to error out while trying to write request data.
webrick/test/webrick/test_httpproxy.rb
Line 189 in ec5372f
th = Thread.new { nr.times { wr.write(rand_str) }; wr.close } |