Commit c65321c70f7 for php

commit c65321c70f7de5f4a4f810f1d23112374d92d1a7
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Tue Oct 13 15:35:12 2026 -0400

    session: close the save handler before session_reset() reopens it (#23597)

    php_session_reset() called php_session_initialize() on an already active
    session, so the save handler's open() and read() ran a second time with no
    intervening close(). Abort the session first, pairing every open() with a
    close().

    Closes GH-23597

diff --git a/NEWS b/NEWS
index e027d6c139e..a7f7caff7ce 100644
--- a/NEWS
+++ b/NEWS
@@ -86,6 +86,8 @@ PHP                                                                        NEWS
     session.use_strict_mode rejects the supplied ID. (Ilia Alshanetsky)
   . Fixed exceptions from user-defined create_sid() handlers being replaced
     by return-value validation errors. (Ilia Alshanetsky)
+  . Fixed calling SessionHandler::open() twice without an intervening
+    close() when re-initializing an active session. (Ilia Alshanetsky)

 - SimpleXML:
   . Fixed bug GH-12171 (SimpleXML property-proxy equality ignores element
diff --git a/ext/session/session.c b/ext/session/session.c
index 3ba2b90f174..5d62245755e 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1809,7 +1809,13 @@ static bool php_session_abort(void)

 static bool php_session_reset(void)
 {
-	return PS(session_status) == php_session_active && php_session_initialize() == SUCCESS;
+	if (PS(session_status) != php_session_active) {
+		return false;
+	}
+
+	php_session_abort();
+
+	return php_session_initialize() == SUCCESS;
 }


diff --git a/ext/session/tests/session_reset_handler_close.phpt b/ext/session/tests/session_reset_handler_close.phpt
new file mode 100644
index 00000000000..94c77757029
--- /dev/null
+++ b/ext/session/tests/session_reset_handler_close.phpt
@@ -0,0 +1,74 @@
+--TEST--
+Session reset closes the save handler before reopening it
+--EXTENSIONS--
+session
+--INI--
+session.use_cookies=0
+session.gc_probability=0
+--FILE--
+<?php
+
+class LoggingHandler implements SessionHandlerInterface, SessionIdInterface, SessionUpdateTimestampHandlerInterface
+{
+    public function open(string $path, string $name): bool
+    {
+        $GLOBALS['calls'][] = 'open';
+        return true;
+    }
+    public function close(): bool
+    {
+        $GLOBALS['calls'][] = 'close';
+        return true;
+    }
+    public function read(string $id): string|false
+    {
+        $GLOBALS['calls'][] = 'read';
+        return '';
+    }
+    public function write(string $id, string $data): bool
+    {
+        $GLOBALS['calls'][] = 'write';
+        return true;
+    }
+    public function destroy(string $id): bool
+    {
+        $GLOBALS['calls'][] = 'destroy';
+        return true;
+    }
+    public function gc(int $max_lifetime): int|false
+    {
+        $GLOBALS['calls'][] = 'gc';
+        return 0;
+    }
+    public function create_sid(): string
+    {
+        return 'testsessionid';
+    }
+    public function validateId(string $id): bool
+    {
+        return true;
+    }
+    public function updateTimestamp(string $id, string $data): bool
+    {
+        return true;
+    }
+}
+
+$GLOBALS['calls'] = [];
+session_set_save_handler(new LoggingHandler(), true);
+var_dump(session_start());
+var_dump(session_reset());
+print_r($GLOBALS['calls']);
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+Array
+(
+    [0] => open
+    [1] => read
+    [2] => close
+    [3] => open
+    [4] => read
+)