Skip to content

Commit f0b426b

Browse files
committed
Fix BasicSocket#{recv,recv_nonblock}, {Socket,UDPSocket}#recvfrom_nonblock, UnixSocket#recvfrom and preserve buffer's encoding
1 parent bae37e4 commit f0b426b

File tree

12 files changed

+116
-13
lines changed

12 files changed

+116
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Bug fixes:
99
* Fix `IO#{wait,wait_readable,wait_writable}` methods and switch the current thread into a sleep state (@andrykonchin).
1010
* Fix `rb_global_variable()` for `Float` and bignum values during the `Init_` function (#3478, @eregon).
1111
* Fix parsing literal floats when the locale does not use `.` for the decimal separator (e.g. `LANG=fr_FR.UTF-8`) (#3512, @eregon).
12-
* Fix `IO#{read_nonblock,readpartial,sysread}` and preserve a provided buffer's encoding (#3506, @andrykonchyn).
12+
* Fix `IO#{read_nonblock,readpartial,sysread}`, `BasicSocket#{recv,recv_nonblock}`, `{Socket,UDPSocket}#recvfrom_nonblock`, `UnixSocket#recvfrom` and preserve a provided buffer's encoding (#3506, @andrykonchyn).
1313

1414
Compatibility:
1515
* Move `IO#wait_readable`, `IO#wait_writable`, `IO#wait_priority` and `IO#wait` into core library (@andrykonchin).

lib/truffle/socket/basic_socket.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,11 @@ def send(message, flags, dest_sockaddr = nil)
163163
end
164164

165165
str = buf.read_string(n_bytes)
166-
buffer ? buffer.replace(str) : str
166+
if buffer
167+
buffer.replace str.force_encoding(buffer.encoding)
168+
else
169+
str
170+
end
167171
end
168172
end
169173

lib/truffle/socket/ip_socket.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ def peeraddr(reverse_lookup = nil)
6161
end
6262
end
6363

64-
message = buffer.replace(message) if buffer
64+
if buffer
65+
message = buffer.replace message.force_encoding(buffer.encoding)
66+
end
6567

6668
[message, [aname, addr.ip_port, hostname, addr.ip_address]]
6769
end

lib/truffle/socket/socket.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ def recvfrom(bytes, flags = 0)
384384
if message == :wait_readable
385385
message
386386
else
387-
message = buffer.replace(message) if buffer
387+
if buffer
388+
message = buffer.replace message.force_encoding(buffer.encoding)
389+
end
388390
[message, addr]
389391
end
390392
end

lib/truffle/socket/unix_socket.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,18 @@ def initialize(path)
5858
Errno.handle('connect(2)') if status < 0
5959
end
6060

61-
def recvfrom(bytes_read, flags = 0)
61+
def recvfrom(bytes_read, flags = 0, buffer = nil)
6262
Truffle::Socket::Foreign.memory_pointer(bytes_read) do |buf|
6363
n_bytes = Truffle::Socket::Foreign.recvfrom(Primitive.io_fd(self), buf, bytes_read, flags, nil, nil)
6464
Errno.handle('recvfrom(2)') if n_bytes == -1
65-
return [buf.read_string(n_bytes), ['AF_UNIX', '']]
65+
66+
message = buf.read_string(n_bytes)
67+
68+
if buffer
69+
message = buffer.replace message.force_encoding(buffer.encoding)
70+
end
71+
72+
return [message, ['AF_UNIX', '']]
6673
end
6774
end
6875

lib/truffle/stringio.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,8 @@ def read(length = nil, buffer = nil)
450450
pos = d.pos
451451
string = d.string
452452

453+
# intentionally don't preserve buffer's encoding
454+
# see https://bugs.ruby-lang.org/issues/20418
453455
if length
454456
length = Truffle::Type.coerce_to length, Integer, :to_int
455457
raise ArgumentError if length < 0

spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,19 @@
5252
@s2.send("data", 0, @s1.getsockname)
5353
IO.select([@s1], nil, nil, 2)
5454

55-
buf = +"foo"
56-
@s1.recv_nonblock(5, 0, buf)
57-
buf.should == "data"
55+
buffer = +"foo"
56+
@s1.recv_nonblock(5, 0, buffer).should.equal?(buffer)
57+
buffer.should == "data"
58+
end
59+
60+
it "preserves the encoding of the given buffer" do
61+
@s1.bind(Socket.pack_sockaddr_in(0, ip_address))
62+
@s2.send("data", 0, @s1.getsockname)
63+
IO.select([@s1], nil, nil, 2)
64+
65+
buffer = ''.encode(Encoding::ISO_8859_1)
66+
@s1.recv_nonblock(5, 0, buffer)
67+
buffer.encoding.should == Encoding::ISO_8859_1
5868
end
5969

6070
it "does not block if there's no data available" do

spec/ruby/library/socket/basicsocket/recv_spec.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,29 @@
100100
socket.write("data")
101101

102102
client = @server.accept
103-
buf = +"foo"
103+
buffer = +"foo"
104104
begin
105-
client.recv(4, 0, buf)
105+
client.recv(4, 0, buffer).should.equal?(buffer)
106106
ensure
107107
client.close
108108
end
109-
buf.should == "data"
109+
buffer.should == "data"
110+
111+
socket.close
112+
end
113+
114+
it "preserves the encoding of the given buffer" do
115+
socket = TCPSocket.new('127.0.0.1', @port)
116+
socket.write("data")
117+
118+
client = @server.accept
119+
buffer = ''.encode(Encoding::ISO_8859_1)
120+
begin
121+
client.recv(4, 0, buffer)
122+
ensure
123+
client.close
124+
end
125+
buffer.encoding.should == Encoding::ISO_8859_1
110126

111127
socket.close
112128
end

spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,27 @@
5252
end
5353
end
5454

55+
it "allows an output buffer as third argument" do
56+
@client.write('hello')
57+
58+
IO.select([@server])
59+
buffer = +''
60+
message, = @server.recvfrom_nonblock(5, 0, buffer)
61+
62+
message.should.equal?(buffer)
63+
buffer.should == 'hello'
64+
end
65+
66+
it "preserves the encoding of the given buffer" do
67+
@client.write('hello')
68+
69+
IO.select([@server])
70+
buffer = ''.encode(Encoding::ISO_8859_1)
71+
@server.recvfrom_nonblock(5, 0, buffer)
72+
73+
buffer.encoding.should == Encoding::ISO_8859_1
74+
end
75+
5576
describe 'the returned data' do
5677
it 'is the same as the sent data' do
5778
5.times do

spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@
5858
buffer.should == 'h'
5959
end
6060

61+
it "preserves the encoding of the given buffer" do
62+
buffer = ''.encode(Encoding::ISO_8859_1)
63+
IO.select([@server])
64+
message, = @server.recvfrom_nonblock(1, 0, buffer)
65+
66+
message.should.equal?(buffer)
67+
buffer.encoding.should == Encoding::ISO_8859_1
68+
end
69+
6170
describe 'the returned Array' do
6271
before do
6372
IO.select([@server])

0 commit comments

Comments
 (0)