Skip to content

Commit a1012fc

Browse files
committed
Merge branch 'maint-3.3'
* maint-3.3: ssl: fix SSLSocket#sysread leaking locktmp String on timeout
2 parents eb7bb6d + a0bf65f commit a1012fc

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

ext/openssl/ossl_ssl.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -1881,9 +1881,10 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
18811881

18821882
VALUE io = rb_attr_get(self, id_i_io);
18831883

1884-
rb_str_locktmp(str);
18851884
for (;;) {
1885+
rb_str_locktmp(str);
18861886
int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1887+
rb_str_unlocktmp(str);
18871888

18881889
cb_state = rb_attr_get(self, ID_callback_state);
18891890
if (!NIL_P(cb_state)) {
@@ -1894,32 +1895,27 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
18941895

18951896
switch (ssl_get_error(ssl, nread)) {
18961897
case SSL_ERROR_NONE:
1897-
rb_str_unlocktmp(str);
18981898
rb_str_set_len(str, nread);
18991899
return str;
19001900
case SSL_ERROR_ZERO_RETURN:
1901-
rb_str_unlocktmp(str);
19021901
if (no_exception_p(opts)) { return Qnil; }
19031902
rb_eof_error();
19041903
case SSL_ERROR_WANT_WRITE:
19051904
if (nonblock) {
1906-
rb_str_unlocktmp(str);
19071905
if (no_exception_p(opts)) { return sym_wait_writable; }
19081906
write_would_block(nonblock);
19091907
}
19101908
io_wait_writable(io);
1911-
continue;
1909+
break;
19121910
case SSL_ERROR_WANT_READ:
19131911
if (nonblock) {
1914-
rb_str_unlocktmp(str);
19151912
if (no_exception_p(opts)) { return sym_wait_readable; }
19161913
read_would_block(nonblock);
19171914
}
19181915
io_wait_readable(io);
1919-
continue;
1916+
break;
19201917
case SSL_ERROR_SYSCALL:
19211918
if (!ERR_peek_error()) {
1922-
rb_str_unlocktmp(str);
19231919
if (errno)
19241920
rb_sys_fail(0);
19251921
else {
@@ -1936,9 +1932,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
19361932
}
19371933
/* fall through */
19381934
default:
1939-
rb_str_unlocktmp(str);
19401935
ossl_raise(eSSLError, "SSL_read");
19411936
}
1937+
1938+
// Ensure the buffer is not modified during io_wait_*able()
1939+
rb_str_modify(str);
1940+
if (rb_str_capacity(str) < (size_t)ilen)
1941+
rb_raise(eSSLError, "read buffer was modified");
19421942
}
19431943
}
19441944

test/openssl/test_ssl.rb

+7-2
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,16 @@ def test_read_with_timeout
255255
ssl.syswrite(str)
256256
assert_equal(str, ssl.sysread(str.bytesize))
257257

258-
ssl.timeout = 1
259-
assert_raise(IO::TimeoutError) {ssl.read(1)}
258+
ssl.timeout = 0.1
259+
assert_raise(IO::TimeoutError) { ssl.sysread(1) }
260260

261261
ssl.syswrite(str)
262262
assert_equal(str, ssl.sysread(str.bytesize))
263+
264+
buf = "orig".b
265+
assert_raise(IO::TimeoutError) { ssl.sysread(1, buf) }
266+
assert_equal("orig", buf)
267+
assert_nothing_raised { buf.clear }
263268
end
264269
end
265270
end

0 commit comments

Comments
 (0)