Skip to content

Commit

Permalink
Fix UDPSocket#(send|write) to raise EMSGSIZE (#4608)
Browse files Browse the repository at this point in the history
* Fix UDPSocket#send msg size error. Relates to #4606

* Add UDPSocket#send EMSGSIZE spec. Relates to #4606

* Fix UDPSocket#write msg size error. Fixes #4606

* Add UDPSocket#write EMSGSIZE spec. Relates to #4606
etehtsea authored and kares committed May 24, 2017
1 parent 205504b commit b04be74
Showing 5 changed files with 55 additions and 8 deletions.
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -3709,6 +3709,10 @@ public RaiseException newErrnoENETUNREACHError() {
return newRaiseException(getErrno().getClass("ENETUNREACH"), null);
}

public RaiseException newErrnoEMSGSIZEError() {
return newRaiseException(getErrno().getClass("EMSGSIZE"), null);
}

public RaiseException newIndexError(String message) {
return newRaiseException(getIndexError(), message);
}
7 changes: 7 additions & 0 deletions core/src/main/java/org/jruby/ext/socket/RubyUDPSocket.java
Original file line number Diff line number Diff line change
@@ -430,6 +430,13 @@ public IRubyObject send(ThreadContext context, IRubyObject[] args) {
} catch (UnknownHostException e) {
throw SocketUtils.sockerr(runtime, "send: name or service not known");
} catch (IOException e) { // SocketException
final String message = e.getMessage();
if (message != null) {
switch(message) {
case "Message too long":
throw runtime.newErrnoEMSGSIZEError();
}
}
throw runtime.newIOErrorFromException(e);
}
catch (RaiseException e) { throw e; }
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Original file line number Diff line number Diff line change
@@ -276,6 +276,7 @@ public static Errno errnoFromException(Throwable t) {

case "No space left on device" : return Errno.ENOSPC;
case "Too many open files" : return Errno.EMFILE;
case "Message too long" : return Errno.EMSGSIZE;
}
if (Platform.IS_WINDOWS && errorMessage.contains("connection was aborted")) return Errno.ECONNRESET;
}
30 changes: 22 additions & 8 deletions spec/ruby/library/socket/udpsocket/send_spec.rb
Original file line number Diff line number Diff line change
@@ -5,16 +5,19 @@
before :each do
@ready = false
@server_thread = Thread.new do
@server = UDPSocket.open
@server.bind(nil, SocketSpecs.port)
@ready = true
begin
@msg = @server.recvfrom_nonblock(64)
rescue IO::WaitReadable
IO.select([@server])
retry
@server = UDPSocket.open
@server.bind(nil, SocketSpecs.port)
@ready = true
begin
@msg = @server.recvfrom_nonblock(64)
rescue IO::WaitReadable
IO.select([@server])
retry
end
ensure
@server.close if @server && !@server.closed?
end
@server.close
end
Thread.pass while @server_thread.status and !@ready
end
@@ -55,4 +58,15 @@
@msg[1][1].should be_kind_of(Fixnum)
@msg[1][3].should == "127.0.0.1"
end

it "raises EMSGSIZE if data is too too big" do
@socket = UDPSocket.open

lambda do
@socket.send('1' * 100_000, 0, SocketSpecs.hostname, SocketSpecs.str_port)
end.should raise_error(Errno::EMSGSIZE)

@socket.close
@server_thread.exit
end
end
21 changes: 21 additions & 0 deletions spec/ruby/library/socket/udpsocket/write_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

describe "UDPSocket#write" do
it "raises EMSGSIZE if msg is too long" do
begin
host, port = SocketSpecs.hostname, SocketSpecs.port
s1 = UDPSocket.new
s1.bind(host, port)
s2 = UDPSocket.new
s2.connect(host, port)

lambda do
s2.write('1' * 100_000)
end.should raise_error(Errno::EMSGSIZE)
ensure
s1.close if s1 && !s1.closed?
s2.close if s2 && !s2.closed?
end
end
end

0 comments on commit b04be74

Please sign in to comment.