Commit 30ae72d5295 for php.net

commit 30ae72d5295e68fd89360f5c19c89bdbd65ff9d7
Merge: 77d4c7f7dda 495c4947c67
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Tue Sep 22 20:51:38 2026 -0400

    Merge branch 'PHP-8.5' into PHP-8.6

    * PHP-8.5:
      ext/session: Abort strict-mode re-creation when create_sid() fails

diff --cc NEWS
index 5bac8f9cb13,a8ff0d7580d..108c9ee8fe2
--- a/NEWS
+++ b/NEWS
@@@ -92,10 -73,10 +92,14 @@@ PH
    . Fixed a heap over-read in the interactive shell prompt when cli.prompt is
      set to an empty string. (Ilia Alshanetsky)

+ - Session:
+   . Fixed session_start() continuing after a failed create_sid() when
+     session.use_strict_mode rejects the supplied ID. (Ilia Alshanetsky)
+
 +- SPL:
 +  . Fixed bug GH-23385 (SplDoublyLinkedList::serialize() use-after-free when
 +    __serialize() removes an element). (David Carlier)
 +
  - SQLite:
    . Fixed a crash when SQLite3::close() is called from a userland callback.
      (Ilia Alshanetsky)
diff --cc ext/session/session.c
index 21545ecc01b,46806b9ff0b..ef97f856499
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@@ -459,14 -471,20 +459,18 @@@ static zend_result php_session_initiali
  	} else if (PS(use_strict_mode) && PS(mod)->s_validate_sid &&
  		PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == FAILURE
  	) {
 -		if (PS(id)) {
 -			zend_string_release_ex(PS(id), 0);
 -			PS(id) = NULL;
 -		}
 +		zend_string_release_ex(PS(id), false);
 +		PS(id) = NULL;
  		PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
  		if (!PS(id)) {
- 			PS(id) = php_session_create_id(NULL);
+ 			php_session_abort();
+ 			if (!EG(exception)) {
+ 				zend_throw_error(NULL, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path)));
+ 			}
+ 			return FAILURE;
  		}
  		if (PS(use_cookies)) {
 -			PS(send_cookie) = 1;
 +			PS(send_cookie) = true;
  		}
  	}

diff --cc ext/session/tests/user_session_module/session_start_strict_recreate_create_sid_fails.phpt
index 00000000000,3c3ac1dea32..3e32c79641e
mode 000000,100644..100644
--- a/ext/session/tests/user_session_module/session_start_strict_recreate_create_sid_fails.phpt
+++ b/ext/session/tests/user_session_module/session_start_strict_recreate_create_sid_fails.phpt
@@@ -1,0 -1,49 +1,49 @@@
+ --TEST--
+ session_start() strict mode re-creation must abort when create_sid fails
+ --INI--
+ session.use_trans_sid=1
+ session.use_only_cookies=0
+ error_reporting=E_ALL & ~E_DEPRECATED
+ --EXTENSIONS--
+ session
+ --FILE--
+ <?php
+
+ class FailingHandler implements SessionHandlerInterface, SessionIdInterface, SessionUpdateTimestampHandlerInterface
+ {
+     public function open($path, $name): bool { return true; }
+     public function close(): bool { return true; }
+     public function read($id): string|false { return ''; }
+     public function write($id, $data): bool { return true; }
+     public function destroy($id): bool { return true; }
+     public function gc($max_lifetime): int|false { return 0; }
+     public function updateTimestamp($id, $data): bool { return true; }
+
+     public function create_sid(): string
+     {
+         throw new RuntimeException('create_sid failed');
+     }
+
+     public function validateId($id): bool
+     {
+         return false;
+     }
+ }
+
+ session_set_save_handler(new FailingHandler(), true);
+ session_id(str_repeat('a', 32));
+
+ try {
+     var_dump(session_start(['use_strict_mode' => true]));
+ } catch (Throwable $e) {
+     echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+ }
+
+ var_dump(session_status() === PHP_SESSION_ACTIVE);
+ var_dump(defined('SID'));
+
+ ?>
+ --EXPECT--
 -Error: Session id must be a string
++TypeError: Session id must be of type string, null given
+ bool(false)
+ bool(false)