Skip to content

Commit 09a57d3

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0: Actually fix GH-9583
2 parents e9a8892 + 499fbcd commit 09a57d3

File tree

2 files changed

+69
-14
lines changed

2 files changed

+69
-14
lines changed

ext/session/session.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,9 +1082,10 @@ PHPAPI int php_session_register_module(const ps_module *ptr) /* {{{ */
10821082
/* }}} */
10831083

10841084
/* Dummy PS module function */
1085-
/* We consider any ID valid, so we return FAILURE to indicate that a session doesn't exist */
1085+
/* We consider any ID valid (thus also implying that a session with such an ID exists),
1086+
thus we always return SUCCESS */
10861087
PHPAPI int php_session_validate_sid(PS_VALIDATE_SID_ARGS) {
1087-
return FAILURE;
1088+
return SUCCESS;
10881089
}
10891090

10901091
/* Dummy PS module function */
@@ -2259,18 +2260,24 @@ PHP_FUNCTION(session_regenerate_id)
22592260
}
22602261
RETURN_THROWS();
22612262
}
2262-
if (PS(use_strict_mode) && PS(mod)->s_validate_sid &&
2263-
PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == SUCCESS) {
2264-
zend_string_release_ex(PS(id), 0);
2265-
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
2266-
if (!PS(id)) {
2267-
PS(mod)->s_close(&PS(mod_data));
2268-
PS(session_status) = php_session_none;
2269-
if (!EG(exception)) {
2270-
zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path));
2263+
if (PS(use_strict_mode)) {
2264+
if ((!PS(mod_user_implemented) && PS(mod)->s_validate_sid) || !Z_ISUNDEF(PS(mod_user_names).name.ps_validate_sid)) {
2265+
int limit = 3;
2266+
/* Try to generate non-existing ID */
2267+
while (limit-- && PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == SUCCESS) {
2268+
zend_string_release_ex(PS(id), 0);
2269+
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
2270+
if (!PS(id)) {
2271+
PS(mod)->s_close(&PS(mod_data));
2272+
PS(session_status) = php_session_none;
2273+
if (!EG(exception)) {
2274+
zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path));
2275+
}
2276+
RETURN_THROWS();
2277+
}
22712278
}
2272-
RETURN_THROWS();
22732279
}
2280+
// TODO warn that ID cannot be verified? else { }
22742281
}
22752282
/* Read is required to make new session data at this point. */
22762283
if (PS(mod)->s_read(&PS(mod_data), PS(id), &data, PS(gc_maxlifetime)) == FAILURE) {
@@ -2297,7 +2304,6 @@ PHP_FUNCTION(session_regenerate_id)
22972304
/* }}} */
22982305

22992306
/* {{{ Generate new session ID. Intended for user save handlers. */
2300-
/* This is not used yet */
23012307
PHP_FUNCTION(session_create_id)
23022308
{
23032309
zend_string *prefix = NULL, *new_id;
@@ -2321,7 +2327,7 @@ PHP_FUNCTION(session_create_id)
23212327
int limit = 3;
23222328
while (limit--) {
23232329
new_id = PS(mod)->s_create_sid(&PS(mod_data));
2324-
if (!PS(mod)->s_validate_sid) {
2330+
if (!PS(mod)->s_validate_sid || (PS(mod_user_implemented) && Z_ISUNDEF(PS(mod_user_names).name.ps_validate_sid))) {
23252331
break;
23262332
} else {
23272333
/* Detect collision and retry */

ext/session/tests/gh9583-extra.phpt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
GH-9583: session_create_id() fails with user defined save handler that doesn't have a validateId() method
3+
--EXTENSIONS--
4+
session
5+
--SKIPIF--
6+
<?php include('skipif.inc'); ?>
7+
--FILE--
8+
<?php
9+
10+
class SessionHandlerTester implements \SessionHandlerInterface
11+
{
12+
13+
public function close(): bool { return true; }
14+
15+
public function destroy($id): bool { return true; }
16+
17+
public function gc($max_lifetime): int|false { return 1; }
18+
19+
public function open($path, $name): bool { return true; }
20+
21+
public function read($id): string { return ''; }
22+
23+
public function write($id, $data): bool { return true; }
24+
25+
//public function create_sid() { return uniqid(); }
26+
27+
//public function validateId($key) { return true; }
28+
}
29+
30+
$obj = new SessionHandlerTester();
31+
ini_set('session.use_strict_mode','1');
32+
session_set_save_handler($obj);
33+
session_start();
34+
35+
$originalSessionId = session_id();
36+
37+
session_write_close();
38+
39+
session_start();
40+
41+
$newSessionId = session_id();
42+
43+
echo 'validateId() ', (method_exists($obj, 'validateId') ? ('returns ' . ($obj->validateId(1) ? 'true' : 'false')) : 'is commented out'), "\n";
44+
var_dump($originalSessionId == $newSessionId);
45+
46+
?>
47+
--EXPECT--
48+
validateId() is commented out
49+
bool(true)

0 commit comments

Comments
 (0)