@@ -218,6 +218,88 @@ def test_synthetic_io_write_nonblock_exception
218218 end
219219 end
220220
221+ def test_synthetic_io_errors_in_servername_cb
222+ assert_separately ( [ "-ropenssl" ] , <<~"end;" )
223+ begin
224+ #sock1, sock2 = socketpair
225+ sock1, sock2 = if defined? UNIXSocket
226+ UNIXSocket.pair
227+ else
228+ Socket.pair(Socket::AF_INET, Socket::SOCK_STREAM, 0)
229+ end
230+
231+ t = Thread.new {
232+ s1 = OpenSSL::SSL::SSLSocket.new(sock1)
233+ s1.hostname = "localhost"
234+ assert_raise_with_message(OpenSSL::SSL::SSLError, /unrecognized.name/i) {
235+ s1.connect
236+ }
237+ }
238+
239+ ctx2 = OpenSSL::SSL::SSLContext.new
240+ ctx2.servername_cb = lambda { |args| raise RuntimeError, "exc in servername_cb" }
241+ obj = Object.new
242+ obj.define_singleton_method(:method_missing) { |name, *args, **kwargs| sock2.__send__(name, *args, **kwargs) }
243+ obj.define_singleton_method(:respond_to_missing?) { |name, *args, **kwargs| sock2.respond_to?(name, *args, **kwargs) }
244+ obj.define_singleton_method(:write_nonblock) { |*args, **kwargs|
245+ begin
246+ raise "exc in write_nonblock"
247+ rescue
248+ p $!
249+ end
250+ p $!
251+ sock2.write_nonblock(*args, **kwargs)
252+ }
253+ s2 = OpenSSL::SSL::SSLSocket.new(obj, ctx2)
254+ assert_raise_with_message(RuntimeError, "exc in servername_cb") { s2.accept }
255+ assert t.join
256+ ensure
257+ sock1.close
258+ sock2.close
259+ end
260+ end;
261+ end
262+
263+ def test_synthetic_io_errors_in_callback_and_socket
264+ assert_separately ( [ "-ropenssl" ] , <<~"end;" )
265+ begin
266+ #sock1, sock2 = socketpair
267+ sock1, sock2 = if defined? UNIXSocket
268+ UNIXSocket.pair
269+ else
270+ Socket.pair(Socket::AF_INET, Socket::SOCK_STREAM, 0)
271+ end
272+
273+ t = Thread.new {
274+ s1 = OpenSSL::SSL::SSLSocket.new(sock1)
275+ s1.hostname = "localhost"
276+ assert_raise_with_message(OpenSSL::SSL::SSLError, /unrecognized.name/i) {
277+ s1.connect
278+ }
279+ }
280+
281+ ctx2 = OpenSSL::SSL::SSLContext.new
282+ ctx2.servername_cb = lambda { |args|
283+ throw :throw_from, :servername_cb
284+ }
285+ obj = Object.new
286+ obj.define_singleton_method(:method_missing) { |name, *args, **kwargs| sock2.__send__(name, *args, **kwargs) }
287+ obj.define_singleton_method(:respond_to_missing?) { |name, *args, **kwargs| sock2.respond_to?(name, *args, **kwargs) }
288+ obj.define_singleton_method(:write_nonblock) { |*args, **kwargs|
289+ raise "write_nonblock"
290+ }
291+ s2 = OpenSSL::SSL::SSLSocket.new(obj, ctx2)
292+
293+ ret = catch(:throw_from) { s2.accept }
294+ assert_equal(:servername_cb, ret)
295+ assert t.join
296+ ensure
297+ sock1.close
298+ sock2.close
299+ end
300+ end;
301+ end
302+
221303 def test_add_certificate
222304 ctx_proc = -> ctx {
223305 # Unset values set by start_server
0 commit comments