Skip to content

Commit 6737867

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-24534: inheritance cache records unlinked child dependencies
2 parents 8dace27 + 614f935 commit 6737867

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

‎Zend/zend_inheritance.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ static void track_class_dependency(zend_class_entry *ce, zend_string *class_name
405405

406406
ht = (HashTable*)CG(current_linking_class)->inheritance_cache;
407407

408-
if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
408+
if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE) || !(ce->ce_flags & ZEND_ACC_LINKED)) {
409409
// TODO: dependency on not-immutable class ???
410410
if (ht) {
411411
zend_hash_destroy(ht);

‎ext/opcache/tests/gh24534.phpt‎

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
--TEST--
2+
GH-24534: Inheritance cache must not record an unlinked child as a dependency
3+
--CREDITS--
4+
Wim Winterberg
5+
--EXTENSIONS--
6+
opcache
7+
--CONFLICTS--
8+
server
9+
--FILE--
10+
<?php
11+
$dir = __DIR__ . '/gh24534';
12+
@mkdir($dir . '/src', 0777, true);
13+
14+
file_put_contents($dir . '/autoload.php', <<<'PHP'
15+
<?php
16+
spl_autoload_register(static function (string $class): void {
17+
$file = __DIR__ . '/src/' . $class . '.php';
18+
if (is_file($file)) {
19+
require $file;
20+
}
21+
});
22+
PHP);
23+
24+
file_put_contents($dir . '/src/EntityInterface.php', <<<'PHP'
25+
<?php
26+
interface EntityInterface
27+
{
28+
public static function getById(int $id): ?self;
29+
}
30+
PHP);
31+
32+
file_put_contents($dir . '/src/Entity.php', <<<'PHP'
33+
<?php
34+
abstract class Entity implements EntityInterface
35+
{
36+
protected array $data = [];
37+
}
38+
PHP);
39+
40+
file_put_contents($dir . '/src/UserBase.php', <<<'PHP'
41+
<?php
42+
abstract class UserBase extends Entity
43+
{
44+
public const TABLE = 'user';
45+
46+
protected ?int $userId = null;
47+
48+
public static function getById(int $id): ?User
49+
{
50+
return null;
51+
}
52+
}
53+
PHP);
54+
55+
file_put_contents($dir . '/src/User.php', <<<'PHP'
56+
<?php
57+
class User extends UserBase
58+
{
59+
}
60+
PHP);
61+
62+
file_put_contents($dir . '/base-first.php', <<<'PHP'
63+
<?php
64+
require __DIR__ . '/autoload.php';
65+
echo 'base-first: ', UserBase::TABLE, PHP_EOL;
66+
PHP);
67+
68+
file_put_contents($dir . '/child-first.php', <<<'PHP'
69+
<?php
70+
require __DIR__ . '/autoload.php';
71+
echo 'child-first: ', User::TABLE, PHP_EOL;
72+
PHP);
73+
74+
include 'php_cli_server.inc';
75+
$ini = trim((string) getenv('TEST_PHP_EXTRA_ARGS'));
76+
$ini .= ($ini !== '' ? ' ' : '') . '-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.file_update_protection=0';
77+
php_cli_server_start($ini);
78+
79+
foreach (['base-first', 'child-first', 'base-first'] as $page) {
80+
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/gh24534/' . $page . '.php');
81+
}
82+
?>
83+
--CLEAN--
84+
<?php
85+
$dir = __DIR__ . '/gh24534';
86+
foreach (['src/EntityInterface.php', 'src/Entity.php', 'src/UserBase.php', 'src/User.php', 'autoload.php', 'base-first.php', 'child-first.php'] as $file) {
87+
@unlink($dir . '/' . $file);
88+
}
89+
@rmdir($dir . '/src');
90+
@rmdir($dir);
91+
?>
92+
--EXPECT--
93+
base-first: user
94+
child-first: user
95+
base-first: user

0 commit comments

Comments
 (0)