Skip to content

Commit 37dd563

Browse files
committed
fix: regression of request-local ordinary-object clone path
1 parent 1a99a96 commit 37dd563

4 files changed

Lines changed: 338 additions & 38 deletions

File tree

ext/opcache/opcache.stub.php

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,6 @@ enum CacheStrategy: int
7575
case Tracking = 1;
7676
}
7777

78-
enum CacheStoreType
79-
{
80-
case NotFound;
81-
case Scalar;
82-
case SharedGraph;
83-
case OPcacheSerialized;
84-
case PHPSerialized;
85-
}
86-
8778
#[\Attribute(13)] /* TARGET_CLASS | TARGET_METHOD | TARGET_PROPERTY */
8879
final class VolatileStatic
8980
{
@@ -121,13 +112,7 @@ public function lock(string $key, int $lease = 0): bool;
121112

122113
public function unlock(string $key): bool;
123114

124-
public function getCacheStoreType(string $key): CacheStoreType;
125-
126115
public static function info(): StaticCacheInfo;
127-
128-
public static function getCacheStoreTypeByProperty(string $class_name, string $property_name): CacheStoreType;
129-
130-
public static function getCacheStoreTypeByMethod(string $class_name, string $method_name, string $variable_name): CacheStoreType;
131116
}
132117

133118
/** @not-serializable */
@@ -160,13 +145,7 @@ public function lock(string $key, int $lease = 0): bool {}
160145

161146
public function unlock(string $key): bool {}
162147

163-
public function getCacheStoreType(string $key): CacheStoreType {}
164-
165148
public static function info(): StaticCacheInfo {}
166-
167-
public static function getCacheStoreTypeByProperty(string $class_name, string $property_name): CacheStoreType {}
168-
169-
public static function getCacheStoreTypeByMethod(string $class_name, string $method_name, string $variable_name): CacheStoreType {}
170149
}
171150

172151
/** @not-serializable */
@@ -207,13 +186,7 @@ public function increment(string $key, int $step = 1): int|false {}
207186

208187
public function decrement(string $key, int $step = 1): int|false {}
209188

210-
public function getCacheStoreType(string $key): CacheStoreType {}
211-
212189
public static function info(): StaticCacheInfo {}
213-
214-
public static function getCacheStoreTypeByProperty(string $class_name, string $property_name): CacheStoreType {}
215-
216-
public static function getCacheStoreTypeByMethod(string $class_name, string $method_name, string $variable_name): CacheStoreType {}
217190
}
218191

219192
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--TEST--
2+
OPcache explicit object fetch keeps array properties isolated on request-local clone
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.static_cache.volatile_size_mb=32
9+
opcache.static_cache.stable_size_mb=32
10+
--FILE--
11+
<?php
12+
13+
final class ExplicitObjectArrayPropertyChild
14+
{
15+
public function __construct(public string $label) {}
16+
}
17+
18+
final class ExplicitObjectArrayPropertyPayload
19+
{
20+
public array $scalarTree;
21+
public array $objectTree;
22+
23+
public function __construct(string $prefix)
24+
{
25+
$child = new ExplicitObjectArrayPropertyChild($prefix . '-child');
26+
$this->scalarTree = [
27+
'routes' => [
28+
['name' => $prefix . '-route-0', 'score' => 10],
29+
['name' => $prefix . '-route-1', 'score' => 20],
30+
],
31+
'meta' => ['owner' => $prefix, 'enabled' => true],
32+
];
33+
$this->objectTree = [
34+
'primary' => $child,
35+
'alias' => $child,
36+
];
37+
}
38+
}
39+
40+
function check_array_property_clone(string $name, object $cache): void
41+
{
42+
$cache->store('object_array_property', new ExplicitObjectArrayPropertyPayload($name));
43+
44+
$first = $cache->fetch('object_array_property');
45+
$warm = $cache->fetch('object_array_property');
46+
var_dump($first === $warm);
47+
var_dump($first->objectTree['primary'] === $first->objectTree['alias']);
48+
var_dump($warm->objectTree['primary'] === $warm->objectTree['alias']);
49+
var_dump($first->objectTree['primary'] === $warm->objectTree['primary']);
50+
51+
$first->scalarTree['routes'][0]['name'] = $name . '-first-mutated-route';
52+
$first->objectTree['primary']->label = $name . '-first-mutated-child';
53+
54+
$second = $cache->fetch('object_array_property');
55+
var_dump($first === $second);
56+
var_dump($second->objectTree['primary'] === $second->objectTree['alias']);
57+
var_dump($first->objectTree['primary'] === $second->objectTree['primary']);
58+
echo $name, '-second-route=', $second->scalarTree['routes'][0]['name'], "\n";
59+
echo $name, '-second-child=', $second->objectTree['primary']->label, "\n";
60+
61+
$second->scalarTree['meta']['owner'] = $name . '-second-mutated-owner';
62+
echo $name, '-first-owner=', $first->scalarTree['meta']['owner'], "\n";
63+
64+
$third = $cache->fetch('object_array_property');
65+
echo $name, '-third-owner=', $third->scalarTree['meta']['owner'], "\n";
66+
echo $name, '-third-child=', $third->objectTree['primary']->label, "\n";
67+
}
68+
69+
opcache_static_cache_volatile_reset();
70+
OPcache\StableCache::getInstance('default')->clear();
71+
72+
check_array_property_clone('volatile', OPcache\VolatileCache::getInstance('default'));
73+
check_array_property_clone('stable', OPcache\StableCache::getInstance('default'));
74+
75+
?>
76+
--EXPECT--
77+
bool(false)
78+
bool(true)
79+
bool(true)
80+
bool(false)
81+
bool(false)
82+
bool(true)
83+
bool(false)
84+
volatile-second-route=volatile-route-0
85+
volatile-second-child=volatile-child
86+
volatile-first-owner=volatile
87+
volatile-third-owner=volatile
88+
volatile-third-child=volatile-child
89+
bool(false)
90+
bool(true)
91+
bool(true)
92+
bool(false)
93+
bool(false)
94+
bool(true)
95+
bool(false)
96+
stable-second-route=stable-route-0
97+
stable-second-child=stable-child
98+
stable-first-owner=stable
99+
stable-third-owner=stable
100+
stable-third-child=stable-child

0 commit comments

Comments
 (0)