ruby-changes:68494
From: Kazuki <ko1@a...>
Date: Sat, 16 Oct 2021 19:53:27 +0900 (JST)
Subject: [ruby-changes:68494] daeb914a52 (master): [ruby/openssl] ssl: temporary lock string buffer while reading
https://git.ruby-lang.org/ruby.git/commit/?id=daeb914a52 From daeb914a525dd7b9faf6ba9f4596deafa22b065a Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi <k@r...> Date: Mon, 30 Aug 2021 18:55:10 +0900 Subject: [ruby/openssl] ssl: temporary lock string buffer while reading Similarly to SSLSocket#syswrite, the blocking SSLSocket#sysread allows context switches. We must prevent other threads from modifying the string buffer. We can use rb_str_locktmp() and rb_str_unlocktmp() to temporarily prohibit modification of the string. https://github.com/ruby/openssl/commit/d38274949f --- ext/openssl/ossl_ssl.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 6d1d84aa5b..1b7586cc88 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1806,26 +1806,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1806 io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); if (ssl_started(ssl)) { - for (;;){ + rb_str_locktmp(str); + for (;;) { nread = SSL_read(ssl, RSTRING_PTR(str), ilen); switch(ssl_get_error(ssl, nread)){ case SSL_ERROR_NONE: + rb_str_unlocktmp(str); goto end; case SSL_ERROR_ZERO_RETURN: + rb_str_unlocktmp(str); if (no_exception_p(opts)) { return Qnil; } rb_eof_error(); case SSL_ERROR_WANT_WRITE: - if (no_exception_p(opts)) { return sym_wait_writable; } - write_would_block(nonblock); + if (nonblock) { + rb_str_unlocktmp(str); + if (no_exception_p(opts)) { return sym_wait_writable; } + write_would_block(nonblock); + } io_wait_writable(fptr); continue; case SSL_ERROR_WANT_READ: - if (no_exception_p(opts)) { return sym_wait_readable; } - read_would_block(nonblock); + if (nonblock) { + rb_str_unlocktmp(str); + if (no_exception_p(opts)) { return sym_wait_readable; } + read_would_block(nonblock); + } io_wait_readable(fptr); continue; case SSL_ERROR_SYSCALL: if (!ERR_peek_error()) { + rb_str_unlocktmp(str); if (errno) rb_sys_fail(0); else { @@ -1842,6 +1852,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1852 } /* fall through */ default: + rb_str_unlocktmp(str); ossl_raise(eSSLError, "SSL_read"); } } -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/