Skip to content

Commit 919fa44

Browse files
committed
Raise an exception if the IO object passed to SSLSocket isn't a file
SSLSocket#connect eventually calls `GetOpenFile` in order to get the underlying file descriptor for the IO object passed in on initialization. `GetOpenFile` assumes that the Ruby object passed in is a T_FILE object and just casts it to a T_FILE without any checks. If you pass an object that *isn't* a T_FILE to that function, the program will segv. Since we assume the IO object is a file in the `connect` method, this commit adds a `CheckType` in the initialize method to ensure that the IO object is actually a T_FILE. If the object *isn't* a T_FILE, this class will segv on `connect`, so I think this is a backwards compatible change.
1 parent 2b3b29b commit 919fa44

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

ext/openssl/ossl_ssl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
15271527

15281528
if (rb_respond_to(io, rb_intern("nonblock=")))
15291529
rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
1530+
Check_Type(io, T_FILE);
15301531
rb_ivar_set(self, id_i_io, io);
15311532

15321533
ssl = SSL_new(ctx);

test/openssl/test_ssl.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
if defined?(OpenSSL)
55

66
class OpenSSL::TestSSL < OpenSSL::SSLTestCase
7+
def test_bad_socket
8+
bad_socket = Struct.new(:sync).new
9+
assert_raises TypeError do
10+
socket = OpenSSL::SSL::SSLSocket.new bad_socket
11+
# if the socket is not a T_FILE, `connect` will segv because it tries
12+
# to get the underlying file descriptor but the API it calls assumes
13+
# the object type is T_FILE
14+
socket.connect
15+
end
16+
end
17+
718
def test_ctx_options
819
ctx = OpenSSL::SSL::SSLContext.new
920

0 commit comments

Comments
 (0)