@@ -218,6 +218,60 @@ def test_synthetic_io_write_nonblock_exception
218218 end
219219 end
220220
221+ def test_synthetic_io_double_error_in_write_then_in_read
222+ pend "FIXME: Write a test case. It appears that OpenSSL may try to write " \
223+ "to the underlying IO after reading from it fails."
224+ end
225+
226+ def test_synthetic_io_double_error_in_cb_then_in_write
227+ # If SSLContext#servername_cb fails, it must send the "unrecognized_name"
228+ # alert. If another error occurs while writing the alert to the underlying
229+ # socket, the original exception from the servername_cb is suppressed.
230+ sock1 , sock2 = socketpair
231+
232+ t = Thread . new {
233+ s1 = OpenSSL ::SSL ::SSLSocket . new ( sock1 )
234+ s1 . hostname = "localhost"
235+ begin
236+ s1 . connect
237+ rescue
238+ end
239+ }
240+
241+ called = [ ]
242+ ctx2 = OpenSSL ::SSL ::SSLContext . new
243+ ctx2 . servername_cb = lambda { |args |
244+ called << :servername_cb
245+ raise "servername_cb"
246+ }
247+ obj = Object . new
248+ obj . define_singleton_method ( :method_missing ) { |name , *args , **kwargs | sock2 . __send__ ( name , *args , **kwargs ) }
249+ obj . define_singleton_method ( :respond_to_missing? ) { |name , *args , **kwargs | sock2 . respond_to? ( name , *args , **kwargs ) }
250+ obj . define_singleton_method ( :write_nonblock ) { |*args , **kwargs |
251+ called << :write_nonblock
252+ throw :throw_from , :write_nonblock
253+ }
254+ s2 = OpenSSL ::SSL ::SSLSocket . new ( obj , ctx2 )
255+
256+ ret = assert_warning ( /exception ignored/ ) {
257+ catch ( :throw_from ) { s2 . accept }
258+ }
259+ assert_equal ( :write_nonblock , ret )
260+ assert_equal ( [ :servername_cb , :write_nonblock ] , called )
261+ sock2 . close
262+ assert t . join
263+ ensure
264+ sock1 . close
265+ sock2 . close
266+ t . kill . join
267+ end
268+
269+ def test_synthetic_io_double_error_in_write_then_in_cb
270+ pend "FIXME: if an underlying IO fails with an exception " \
271+ "and then a callback is called, it will likely lead to crash. " \
272+ "Does this actually happen? Need to review the code paths."
273+ end
274+
221275 def test_add_certificate
222276 ctx_proc = -> ctx {
223277 # Unset values set by start_server
0 commit comments