Skip to content

Commit 9c460bb

Browse files
committed
Add persistent stream context shutdown reproducer
1 parent ed60b9e commit 9c460bb

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

‎NEWS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ PHP NEWS
113113
. Fixed three Windows-only proc_open() defects: an uninitialized
114114
PROCESS_INFORMATION, an indeterminate comspec pointer after a failed
115115
lookup, and an unchecked CreateFileA() failure. (Ilia Alshanetsky)
116+
. Fix persistent stream context lifetime during shutdown (Levi Morrison)
116117

117118
- XSL:
118119
. Fixed bug GH-23730 (use-after-free when XSLTProcessor::importStylesheet()
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
--TEST--
2+
Persistent stream contexts created during resource shutdown are detached
3+
--FILE--
4+
<?php
5+
6+
if (($argv[1] ?? null) !== 'child') {
7+
// Wait for the trigger's final status because the crash occurs after stdout closes.
8+
$process = proc_open(
9+
[PHP_BINARY, '-n', __FILE__, 'child'],
10+
[
11+
0 => ['pipe', 'r'],
12+
1 => ['pipe', 'w'],
13+
2 => ['pipe', 'w'],
14+
],
15+
$pipes,
16+
);
17+
fclose($pipes[0]);
18+
stream_get_contents($pipes[1]);
19+
fclose($pipes[1]);
20+
stream_get_contents($pipes[2]);
21+
fclose($pipes[2]);
22+
var_dump(proc_close($process));
23+
return;
24+
}
25+
26+
final class LateContextWrapper
27+
{
28+
public $context;
29+
private string $address;
30+
31+
public function stream_open($path, $mode, $options, &$opened_path): bool
32+
{
33+
$this->address = substr($path, strlen('late-context://'));
34+
return true;
35+
}
36+
37+
public function stream_close(): void
38+
{
39+
$context = stream_context_create([
40+
'socket' => ['tcp_nodelay' => true],
41+
]);
42+
stream_socket_client(
43+
$this->address,
44+
$errno,
45+
$error,
46+
1,
47+
STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT,
48+
$context,
49+
);
50+
}
51+
}
52+
53+
$server = stream_socket_server('tcp://127.0.0.1:0', $errno, $error);
54+
if (!$server) {
55+
die("server failed: $error ($errno)\n");
56+
}
57+
58+
stream_wrapper_register('late-context', LateContextWrapper::class);
59+
$trigger = fopen('late-context://tcp://' . stream_socket_get_name($server, false), 'r');
60+
61+
?>
62+
--EXPECT--
63+
int(0)

0 commit comments

Comments
 (0)