зеркало из https://github.com/github/ruby.git
* ext/socket/unixsocket.c (rsock_init_unixsock): Open a socket
after path length check. This fixes a fd leak by TestSocket_UNIXSocket#test_too_long_path. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46218 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
b73eaef7a8
Коммит
eb9f446ebf
|
@ -1,3 +1,9 @@
|
||||||
|
Thu May 29 00:28:56 2014 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* ext/socket/unixsocket.c (rsock_init_unixsock): Open a socket
|
||||||
|
after path length check.
|
||||||
|
This fixes a fd leak by TestSocket_UNIXSocket#test_too_long_path.
|
||||||
|
|
||||||
Wed May 28 23:04:35 2014 Tanaka Akira <akr@fsij.org>
|
Wed May 28 23:04:35 2014 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* test/ruby/test_io.rb (test_flush_in_finalizer1): Use
|
* test/ruby/test_io.rb (test_flush_in_finalizer1): Use
|
||||||
|
|
|
@ -34,10 +34,6 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server)
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
|
|
||||||
SafeStringValue(path);
|
SafeStringValue(path);
|
||||||
fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (fd < 0) {
|
|
||||||
rsock_sys_fail_path("socket(2)", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
|
INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
|
||||||
if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
|
if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
|
||||||
|
@ -47,6 +43,11 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server)
|
||||||
memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
|
memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
|
||||||
sockaddrlen = rsock_unix_sockaddr_len(path);
|
sockaddrlen = rsock_unix_sockaddr_len(path);
|
||||||
|
|
||||||
|
fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
rsock_sys_fail_path("socket(2)", path);
|
||||||
|
}
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
|
status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,6 +538,7 @@ class TestSocket < Test::Unit::TestCase
|
||||||
assert_raise(IOError, bug4390) {client_thread.join}
|
assert_raise(IOError, bug4390) {client_thread.join}
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
|
serv_thread.value.close
|
||||||
server.close
|
server.close
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,36 +45,35 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_recvfrom
|
def test_recvfrom
|
||||||
svr = TCPServer.new("localhost", 0)
|
TCPServer.open("localhost", 0) {|svr|
|
||||||
th = Thread.new {
|
th = Thread.new {
|
||||||
c = svr.accept
|
c = svr.accept
|
||||||
c.write "foo"
|
c.write "foo"
|
||||||
c.close
|
c.close
|
||||||
|
}
|
||||||
|
addr = svr.addr
|
||||||
|
TCPSocket.open(addr[3], addr[1]) {|sock|
|
||||||
|
assert_equal(["foo", nil], sock.recvfrom(0x10000))
|
||||||
|
}
|
||||||
|
th.join
|
||||||
}
|
}
|
||||||
addr = svr.addr
|
|
||||||
sock = TCPSocket.open(addr[3], addr[1])
|
|
||||||
assert_equal(["foo", nil], sock.recvfrom(0x10000))
|
|
||||||
ensure
|
|
||||||
th.kill if th
|
|
||||||
th.join if th
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_encoding
|
def test_encoding
|
||||||
svr = TCPServer.new("localhost", 0)
|
TCPServer.open("localhost", 0) {|svr|
|
||||||
th = Thread.new {
|
th = Thread.new {
|
||||||
c = svr.accept
|
c = svr.accept
|
||||||
c.write "foo\r\n"
|
c.write "foo\r\n"
|
||||||
c.close
|
c.close
|
||||||
|
}
|
||||||
|
addr = svr.addr
|
||||||
|
TCPSocket.open(addr[3], addr[1]) {|sock|
|
||||||
|
assert_equal(true, sock.binmode?)
|
||||||
|
s = sock.gets
|
||||||
|
assert_equal("foo\r\n", s)
|
||||||
|
assert_equal(Encoding.find("ASCII-8BIT"), s.encoding)
|
||||||
|
}
|
||||||
|
th.join
|
||||||
}
|
}
|
||||||
addr = svr.addr
|
|
||||||
sock = TCPSocket.open(addr[3], addr[1])
|
|
||||||
assert_equal(true, sock.binmode?)
|
|
||||||
s = sock.gets
|
|
||||||
assert_equal("foo\r\n", s)
|
|
||||||
assert_equal(Encoding.find("ASCII-8BIT"), s.encoding)
|
|
||||||
ensure
|
|
||||||
th.kill if th
|
|
||||||
th.join if th
|
|
||||||
sock.close if sock
|
|
||||||
end
|
end
|
||||||
end if defined?(TCPSocket)
|
end if defined?(TCPSocket)
|
||||||
|
|
|
@ -55,16 +55,20 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
ret = s2.recvmsg(:scm_rights=>true)
|
ret = s2.recvmsg(:scm_rights=>true)
|
||||||
_, _, _, *ctls = ret
|
_, _, _, *ctls = ret
|
||||||
recv_io_ary = []
|
recv_io_ary = []
|
||||||
ctls.each {|ctl|
|
begin
|
||||||
next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
|
ctls.each {|ctl|
|
||||||
recv_io_ary.concat ctl.unix_rights
|
next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
|
||||||
}
|
recv_io_ary.concat ctl.unix_rights
|
||||||
assert_equal(send_io_ary.length, recv_io_ary.length)
|
}
|
||||||
send_io_ary.length.times {|i|
|
assert_equal(send_io_ary.length, recv_io_ary.length)
|
||||||
assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
|
send_io_ary.length.times {|i|
|
||||||
assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
|
assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
|
||||||
assert(recv_io_ary[i].close_on_exec?)
|
assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
|
||||||
}
|
assert(recv_io_ary[i].close_on_exec?)
|
||||||
|
}
|
||||||
|
ensure
|
||||||
|
recv_io_ary.each {|io| io.close if !io.closed? }
|
||||||
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensure
|
ensure
|
||||||
|
@ -92,16 +96,20 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
ret = s2.recvmsg(:scm_rights=>true)
|
ret = s2.recvmsg(:scm_rights=>true)
|
||||||
_, _, _, *ctls = ret
|
_, _, _, *ctls = ret
|
||||||
recv_io_ary = []
|
recv_io_ary = []
|
||||||
ctls.each {|ctl|
|
begin
|
||||||
next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
|
ctls.each {|ctl|
|
||||||
recv_io_ary.concat ctl.unix_rights
|
next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
|
||||||
}
|
recv_io_ary.concat ctl.unix_rights
|
||||||
assert_equal(send_io_ary.length, recv_io_ary.length)
|
}
|
||||||
send_io_ary.length.times {|i|
|
assert_equal(send_io_ary.length, recv_io_ary.length)
|
||||||
assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
|
send_io_ary.length.times {|i|
|
||||||
assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
|
assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
|
||||||
assert(recv_io_ary[i].close_on_exec?)
|
assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
|
||||||
}
|
assert(recv_io_ary[i].close_on_exec?)
|
||||||
|
}
|
||||||
|
ensure
|
||||||
|
recv_io_ary.each {|io| io.close if !io.closed? }
|
||||||
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensure
|
ensure
|
||||||
|
@ -248,31 +256,43 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
tmpfile = Tempfile.new("s")
|
tmpfile = Tempfile.new("s")
|
||||||
path = tmpfile.path
|
path = tmpfile.path
|
||||||
tmpfile.close(true)
|
tmpfile.close(true)
|
||||||
yield klass.new(path), path
|
io = klass.new(path)
|
||||||
|
yield io, path
|
||||||
ensure
|
ensure
|
||||||
|
io.close
|
||||||
File.unlink path if path && File.socket?(path)
|
File.unlink path if path && File.socket?(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_addr
|
def test_addr
|
||||||
bound_unix_socket(UNIXServer) {|serv, path|
|
bound_unix_socket(UNIXServer) {|serv, path|
|
||||||
c = UNIXSocket.new(path)
|
UNIXSocket.open(path) {|c|
|
||||||
s = serv.accept
|
s = serv.accept
|
||||||
assert_equal(["AF_UNIX", path], c.peeraddr)
|
begin
|
||||||
assert_equal(["AF_UNIX", ""], c.addr)
|
assert_equal(["AF_UNIX", path], c.peeraddr)
|
||||||
assert_equal(["AF_UNIX", ""], s.peeraddr)
|
assert_equal(["AF_UNIX", ""], c.addr)
|
||||||
assert_equal(["AF_UNIX", path], s.addr)
|
assert_equal(["AF_UNIX", ""], s.peeraddr)
|
||||||
assert_equal(path, s.path)
|
assert_equal(["AF_UNIX", path], s.addr)
|
||||||
assert_equal("", c.path)
|
assert_equal(path, s.path)
|
||||||
|
assert_equal("", c.path)
|
||||||
|
ensure
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_cloexec
|
def test_cloexec
|
||||||
bound_unix_socket(UNIXServer) {|serv, path|
|
bound_unix_socket(UNIXServer) {|serv, path|
|
||||||
c = UNIXSocket.new(path)
|
UNIXSocket.open(path) {|c|
|
||||||
s = serv.accept
|
s = serv.accept
|
||||||
assert(serv.close_on_exec?)
|
begin
|
||||||
assert(c.close_on_exec?)
|
assert(serv.close_on_exec?)
|
||||||
assert(s.close_on_exec?)
|
assert(c.close_on_exec?)
|
||||||
|
assert(s.close_on_exec?)
|
||||||
|
ensure
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -393,12 +413,13 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_epipe # [ruby-dev:34619]
|
def test_epipe # [ruby-dev:34619]
|
||||||
s1, s2 = UNIXSocket.pair
|
UNIXSocket.pair {|s1, s2|
|
||||||
s1.shutdown(Socket::SHUT_WR)
|
s1.shutdown(Socket::SHUT_WR)
|
||||||
assert_raise(Errno::EPIPE) { s1.write "a" }
|
assert_raise(Errno::EPIPE) { s1.write "a" }
|
||||||
assert_equal(nil, s2.read(1))
|
assert_equal(nil, s2.read(1))
|
||||||
s2.write "a"
|
s2.write "a"
|
||||||
assert_equal("a", s1.read(1))
|
assert_equal("a", s1.read(1))
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_socket_pair_with_block
|
def test_socket_pair_with_block
|
||||||
|
@ -463,15 +484,21 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
return if /linux/ !~ RUBY_PLATFORM
|
return if /linux/ !~ RUBY_PLATFORM
|
||||||
Dir.mktmpdir {|d|
|
Dir.mktmpdir {|d|
|
||||||
sockpath = "#{d}/sock"
|
sockpath = "#{d}/sock"
|
||||||
serv = Socket.unix_server_socket(sockpath)
|
Socket.unix_server_socket(sockpath) {|serv|
|
||||||
Socket.unix(sockpath)
|
Socket.unix(sockpath) {|c|
|
||||||
s, = serv.accept
|
s, = serv.accept
|
||||||
cred = s.getsockopt(:SOCKET, :PEERCRED)
|
begin
|
||||||
inspect = cred.inspect
|
cred = s.getsockopt(:SOCKET, :PEERCRED)
|
||||||
assert_match(/ pid=#{$$} /, inspect)
|
inspect = cred.inspect
|
||||||
assert_match(/ euid=#{Process.euid} /, inspect)
|
assert_match(/ pid=#{$$} /, inspect)
|
||||||
assert_match(/ egid=#{Process.egid} /, inspect)
|
assert_match(/ euid=#{Process.euid} /, inspect)
|
||||||
assert_match(/ \(ucred\)/, inspect)
|
assert_match(/ egid=#{Process.egid} /, inspect)
|
||||||
|
assert_match(/ \(ucred\)/, inspect)
|
||||||
|
ensure
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -493,18 +520,24 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
return if /linux/ !~ RUBY_PLATFORM
|
return if /linux/ !~ RUBY_PLATFORM
|
||||||
Dir.mktmpdir {|d|
|
Dir.mktmpdir {|d|
|
||||||
sockpath = "#{d}/sock"
|
sockpath = "#{d}/sock"
|
||||||
serv = Socket.unix_server_socket(sockpath)
|
Socket.unix_server_socket(sockpath) {|serv|
|
||||||
c = Socket.unix(sockpath)
|
Socket.unix(sockpath) {|c|
|
||||||
s, = serv.accept
|
s, = serv.accept
|
||||||
s.setsockopt(:SOCKET, :PASSCRED, 1)
|
begin
|
||||||
c.print "a"
|
s.setsockopt(:SOCKET, :PASSCRED, 1)
|
||||||
msg, _, _, cred = s.recvmsg
|
c.print "a"
|
||||||
inspect = cred.inspect
|
msg, _, _, cred = s.recvmsg
|
||||||
assert_equal("a", msg)
|
inspect = cred.inspect
|
||||||
assert_match(/ pid=#{$$} /, inspect)
|
assert_equal("a", msg)
|
||||||
assert_match(/ uid=#{Process.uid} /, inspect)
|
assert_match(/ pid=#{$$} /, inspect)
|
||||||
assert_match(/ gid=#{Process.gid} /, inspect)
|
assert_match(/ uid=#{Process.uid} /, inspect)
|
||||||
assert_match(/ \(ucred\)/, inspect)
|
assert_match(/ gid=#{Process.gid} /, inspect)
|
||||||
|
assert_match(/ \(ucred\)/, inspect)
|
||||||
|
ensure
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -550,14 +583,18 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
|
||||||
def test_getpeereid
|
def test_getpeereid
|
||||||
Dir.mktmpdir {|d|
|
Dir.mktmpdir {|d|
|
||||||
path = "#{d}/sock"
|
path = "#{d}/sock"
|
||||||
serv = Socket.unix_server_socket(path)
|
Socket.unix_server_socket(path) {|serv|
|
||||||
c = Socket.unix(path)
|
Socket.unix(path) {|c|
|
||||||
s, = serv.accept
|
s, = serv.accept
|
||||||
begin
|
begin
|
||||||
assert_equal([Process.euid, Process.egid], c.getpeereid)
|
assert_equal([Process.euid, Process.egid], c.getpeereid)
|
||||||
assert_equal([Process.euid, Process.egid], s.getpeereid)
|
assert_equal([Process.euid, Process.egid], s.getpeereid)
|
||||||
rescue NotImplementedError
|
rescue NotImplementedError
|
||||||
end
|
ensure
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче