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

ruby-changes:54368

From: nobu <ko1@a...>
Date: Thu, 27 Dec 2018 13:49:18 +0900 (JST)
Subject: [ruby-changes:54368] nobu:r66582 (trunk): Fix Net::Protocol::BufferedIO#write when sending large multi-byte string

nobu	2018-12-27 13:49:12 +0900 (Thu, 27 Dec 2018)

  New Revision: 66582

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

  Log:
    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: '?\227?\129?\130'*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@g...>

  Modified files:
    trunk/lib/net/protocol.rb
    trunk/test/net/protocol/test_protocol.rb
Index: lib/net/protocol.rb
===================================================================
--- lib/net/protocol.rb	(revision 66581)
+++ lib/net/protocol.rb	(revision 66582)
@@ -286,7 +286,7 @@ module Net # :nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/protocol.rb#L286
               # next string
             end
           elsif len < 0
-            str = str[len, -len]
+            str = str.byteslice(len, -len)
           else # len > 0
             need_retry = false
             # next string
Index: test/net/protocol/test_protocol.rb
===================================================================
--- test/net/protocol/test_protocol.rb	(revision 66581)
+++ test/net/protocol/test_protocol.rb	(revision 66582)
@@ -27,10 +27,10 @@ class TestProtocol < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/net/protocol/test_protocol.rb#L27
     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 @@ class TestProtocol < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/net/protocol/test_protocol.rb#L46
       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 @@ class TestProtocol < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/net/protocol/test_protocol.rb#L55
     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)

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

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