From ccd9baf7f7cc2aa6826dc7a59744a20144d9a905 Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Fri, 28 Aug 2026 03:15:09 +0300 Subject: [PATCH 1/2] Close constructed sessions when server negotiation fails --- lib/websocket/extensions.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/websocket/extensions.rb b/lib/websocket/extensions.rb index 14ca7ab..3ea367a 100644 --- a/lib/websocket/extensions.rb +++ b/lib/websocket/extensions.rb @@ -115,6 +115,12 @@ def generate_response(header) @sessions = sessions response.size > 0 ? response.join(', ') : nil + ensure + if sessions and !sessions.equal?(@sessions) + sessions.each do |ext, session| + session.close rescue nil + end + end end def valid_frame_rsv(frame) From 44058c4c26852324f136679d448180b3483b1ea6 Mon Sep 17 00:00:00 2001 From: Oskar Eichler <62393985+OskarEichler@users.noreply.github.com> Date: Fri, 28 Aug 2026 14:43:35 +0300 Subject: [PATCH 2/2] Add extension lifecycle regression coverage --- spec/websocket/extensions_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/websocket/extensions_spec.rb b/spec/websocket/extensions_spec.rb index ccb305d..e850808 100644 --- a/spec/websocket/extensions_spec.rb +++ b/spec/websocket/extensions_spec.rb @@ -325,6 +325,16 @@ expect(@extensions.generate_response("deflate, tar")).to eq "deflate; mode=compress" end + it "closes constructed sessions when response generation fails" do + allow(@nonconflict_session).to receive(:generate_response).and_raise(TypeError) + expect(@session).to receive(:close).exactly(1) + expect(@nonconflict_session).to receive(:close).exactly(1) + + expect { + @extensions.generate_response("deflate, reverse") + }.to raise_error(TypeError) + end + it "raises an error if the header is invalid" do expect { @extensions.generate_response("x-webkit- -frame") }.to raise_error(WebSocket::Extensions::Parser::ParseError) end