Skip to content

Commit 4a9f0c8

Browse files
committed
session: close save handler before re-initializing an active session
php_session_initialize() set the status to active and called the save handler's open() and read() without first closing a session that was already active, so session_reset() left the earlier open() unmatched. Abort the active session first, pairing every open() with a close(). Closes GH-23597
1 parent 979c827 commit 4a9f0c8

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ PHP NEWS
9292
. Fixed bug GH-23477 (Memory leak on duplicate native Phar manifest entries).
9393
(Weilin Du)
9494

95+
- Session:
96+
. Fixed calling SessionHandler::open() twice without an intervening
97+
close() when re-initializing an active session. (Ilia Alshanetsky)
98+
9599
- SOAP:
96100
. Fixed bug GH-23447 (Segfault when a class passed to SoapServer::setClass()
97101
fails to initialize). (Lazizbek Ergashev)

ext/session/session.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,10 @@ static zend_result php_session_initialize(void) /* {{{ */
420420
{
421421
zend_string *val = NULL;
422422

423+
if (PS(session_status) == php_session_active) {
424+
php_session_abort();
425+
}
426+
423427
PS(session_status) = php_session_active;
424428

425429
if (!PS(mod)) {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--TEST--
2+
Session reset closes the save handler before reopening it
3+
--INI--
4+
session.use_cookies=0
5+
session.gc_probability=0
6+
--FILE--
7+
<?php
8+
9+
class LoggingHandler implements SessionHandlerInterface
10+
{
11+
public function open(string $path, string $name): bool
12+
{
13+
$GLOBALS['calls'][] = 'open';
14+
return true;
15+
}
16+
public function close(): bool
17+
{
18+
$GLOBALS['calls'][] = 'close';
19+
return true;
20+
}
21+
public function read(string $id): string|false
22+
{
23+
$GLOBALS['calls'][] = 'read';
24+
return '';
25+
}
26+
public function write(string $id, string $data): bool
27+
{
28+
$GLOBALS['calls'][] = 'write';
29+
return true;
30+
}
31+
public function destroy(string $id): bool
32+
{
33+
$GLOBALS['calls'][] = 'destroy';
34+
return true;
35+
}
36+
public function gc(int $max_lifetime): int|false
37+
{
38+
$GLOBALS['calls'][] = 'gc';
39+
return 0;
40+
}
41+
}
42+
43+
$GLOBALS['calls'] = [];
44+
session_set_save_handler(new LoggingHandler(), true);
45+
var_dump(session_start());
46+
var_dump(session_reset());
47+
print_r($GLOBALS['calls']);
48+
49+
?>
50+
--EXPECT--
51+
bool(true)
52+
bool(true)
53+
Array
54+
(
55+
[0] => open
56+
[1] => read
57+
[2] => close
58+
[3] => open
59+
[4] => read
60+
)

0 commit comments

Comments
 (0)