Backport of:

From c48e52f7c57e99e1e1bf54c8760d4f082cd1c89d Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@jeremyevans.net>
Date: Tue, 6 May 2025 19:08:57 +0900
Subject: [PATCH] Merge commit from fork

* Make Rack::Session::Pool#write_session fail if session doesn't exist

This fixes a potential security issue if the session is concurrently
deleted by another thread.

* Add test.

* Add CHANGELOG entry.

---------

Co-authored-by: Samuel Williams <samuel.williams@oriontransfer.co.nz>
---
 CHANGELOG.md              |  6 +++++
 lib/rack/session/pool.rb  |  7 +++++-
 test/spec_session_pool.rb | 48 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)

--- a/lib/rack/session/pool.rb
+++ b/lib/rack/session/pool.rb
@@ -55,6 +55,7 @@
 
       def write_session(req, session_id, new_session, options)
         with_lock(req) do
+          return false unless get_session_with_fallback(session_id)
           @pool.store session_id.private_id, new_session
           session_id
         end
@@ -64,7 +65,11 @@
         with_lock(req) do
           @pool.delete(session_id.public_id)
           @pool.delete(session_id.private_id)
-          generate_sid unless options[:drop]
+          unless options[:drop]
+            sid = generate_sid
+            @pool.store(sid.private_id, {})
+            sid
+          end
         end
       end
 
