Skip to content

Commit 7d5ce1c

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Actually fix GH-9583
2 parents 59a19d7 + 09a57d3 commit 7d5ce1c

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
@@ -1068,9 +1068,10 @@ PHPAPI zend_result php_session_register_module(const ps_module *ptr) /* {{{ */
10681068
/* }}} */
10691069

10701070
/* Dummy PS module function */
1071-
/* We consider any ID valid, so we return FAILURE to indicate that a session doesn't exist */
1071+
/* We consider any ID valid (thus also implying that a session with such an ID exists),
1072+
thus we always return SUCCESS */
10721073
PHPAPI zend_result php_session_validate_sid(PS_VALIDATE_SID_ARGS) {
1073-
return FAILURE;
1074+
return SUCCESS;
10741075
}
10751076

10761077
/* Dummy PS module function */
@@ -2254,18 +2255,24 @@ PHP_FUNCTION(session_regenerate_id)
22542255
}
22552256
RETURN_THROWS();
22562257
}
2257-
if (PS(use_strict_mode) && PS(mod)->s_validate_sid &&
2258-
PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == SUCCESS) {
2259-
zend_string_release_ex(PS(id), 0);
2260-
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
2261-
if (!PS(id)) {
2262-
PS(mod)->s_close(&PS(mod_data));
2263-
PS(session_status) = php_session_none;
2264-
if (!EG(exception)) {
2265-
zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path));
2258+
if (PS(use_strict_mode)) {
2259+
if ((!PS(mod_user_implemented) && PS(mod)->s_validate_sid) || !Z_ISUNDEF(PS(mod_user_names).name.ps_validate_sid)) {
2260+
int limit = 3;
2261+
/* Try to generate non-existing ID */
2262+
while (limit-- && PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == SUCCESS) {
2263+
zend_string_release_ex(PS(id), 0);
2264+
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
2265+
if (!PS(id)) {
2266+
PS(mod)->s_close(&PS(mod_data));
2267+
PS(session_status) = php_session_none;
2268+
if (!EG(exception)) {
2269+
zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path));
2270+
}
2271+
RETURN_THROWS();
2272+
}
22662273
}
2267-
RETURN_THROWS();
22682274
}
2275+
// TODO warn that ID cannot be verified? else { }
22692276
}
22702277
/* Read is required to make new session data at this point. */
22712278
if (PS(mod)->s_read(&PS(mod_data), PS(id), &data, PS(gc_maxlifetime)) == FAILURE) {
@@ -2292,7 +2299,6 @@ PHP_FUNCTION(session_regenerate_id)
22922299
/* }}} */
22932300

22942301
/* {{{ Generate new session ID. Intended for user save handlers. */
2295-
/* This is not used yet */
22962302
PHP_FUNCTION(session_create_id)
22972303
{
22982304
zend_string *prefix = NULL, *new_id;
@@ -2316,7 +2322,7 @@ PHP_FUNCTION(session_create_id)
23162322
int limit = 3;
23172323
while (limit--) {
23182324
new_id = PS(mod)->s_create_sid(&PS(mod_data));
2319-
if (!PS(mod)->s_validate_sid) {
2325+
if (!PS(mod)->s_validate_sid || (PS(mod_user_implemented) && Z_ISUNDEF(PS(mod_user_names).name.ps_validate_sid))) {
23202326
break;
23212327
} else {
23222328
/* 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)