Permalink
Browse files

Fix Net::Protocol::BufferedIO#write when sending large multi-byte string

This commit should fix Net::Protocol::BufferedIO#write when sending
large multi-byte string like following example.

```
$ ruby -rnet/http -rjson -v -e "Net::HTTP.post(URI('http://httpbin.org/post'), { text: 'あ'*100_000 }.to_json, 'Content-Type' => 'application/json')"
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
Traceback (most recent call last):
        19: from -e:1:in `<main>'
        18: from lib/ruby/2.6.0/net/http.rb:500:in `post'
        17: from lib/ruby/2.6.0/net/http.rb:605:in `start'
        16: from lib/ruby/2.6.0/net/http.rb:920:in `start'
        15: from lib/ruby/2.6.0/net/http.rb:502:in `block in post'
        14: from lib/ruby/2.6.0/net/http.rb:1281:in `post'
        13: from lib/ruby/2.6.0/net/http.rb:1493:in `send_entity'
        12: from lib/ruby/2.6.0/net/http.rb:1479:in `request'
        11: from lib/ruby/2.6.0/net/http.rb:1506:in `transport_request'
        10: from lib/ruby/2.6.0/net/http.rb:1506:in `catch'
         9: from lib/ruby/2.6.0/net/http.rb:1507:in `block in transport_request'
         8: from lib/ruby/2.6.0/net/http/generic_request.rb:123:in `exec'
         7: from lib/ruby/2.6.0/net/http/generic_request.rb:189:in `send_request_with_body'
         6: from lib/ruby/2.6.0/net/protocol.rb:247:in `write'
         5: from lib/ruby/2.6.0/net/protocol.rb:265:in `writing'
         4: from lib/ruby/2.6.0/net/protocol.rb:248:in `block in write'
         3: from lib/ruby/2.6.0/net/protocol.rb:275:in `write0'
         2: from lib/ruby/2.6.0/net/protocol.rb:275:in `each_with_index'
         1: from lib/ruby/2.6.0/net/protocol.rb:275:in `each'
lib/ruby/2.6.0/net/protocol.rb:280:in `block in write0': undefined method `bytesize' for nil:NilClass (NoMethodError)
```

[Fix GH-2058]

From: Eito Katagiri <eitoball@gmail.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66582 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
nobu committed Dec 27, 2018
1 parent 1f866dd commit 1680a13a926b17661329beec1ded6b32aad16c1b
Showing with 14 additions and 4 deletions.
  1. +1 −1 lib/net/protocol.rb
  2. +13 −3 test/net/protocol/test_protocol.rb
@@ -286,7 +286,7 @@ def write0(*strs)
# next string
end
elsif len < 0
str = str[len, -len]
str = str.byteslice(len, -len)
else # len > 0
need_retry = false
# next string
@@ -27,10 +27,10 @@ def test_each_crlf_line
end
end

def create_mockio
def create_mockio(capacity: 100)
mockio = Object.new
mockio.instance_variable_set(:@str, +'')
mockio.instance_variable_set(:@capacity, 100)
mockio.instance_variable_set(:@capacity, capacity)
def mockio.string; @str; end
def mockio.to_io; self; end
def mockio.wait_writable(sec); sleep sec; false; end
@@ -46,7 +46,7 @@ def mockio.write_nonblock(*strs, exception: true)
strs.each do |str|
len1 = @str.bytesize
break if @capacity <= len1
@str << str[0, @capacity - @str.bytesize]
@str << str.byteslice(0, @capacity - @str.bytesize)
len2 = @str.bytesize
len += len2 - len1
end
@@ -55,6 +55,16 @@ def mockio.write_nonblock(*strs, exception: true)
mockio
end

def test_write0_multibyte
mockio = create_mockio(capacity: 1)
def mockio.write_nonblock(str, *strs, **kw)
@str << str.byteslice(0, 1)
1
end
io = Net::BufferedIO.new(mockio)
assert_equal(3, io.write("\u3042"))
end

def test_write0_timeout
mockio = create_mockio
io = Net::BufferedIO.new(mockio)

0 comments on commit 1680a13

Please sign in to comment.