Skip to content

Commit 9c8e80b

Browse files
committed
Made sure properties are still readonly after clone-with
1 parent 119163a commit 9c8e80b

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Properties are still readonly after clone-with
3+
--FILE--
4+
<?php
5+
6+
readonly class Test {
7+
public public(set) int $a;
8+
public public(set) int $b;
9+
10+
public function __construct() {
11+
$this->a = 1;
12+
$this->b = 2;
13+
}
14+
}
15+
16+
$test = clone(new Test(), ['a' => 3]);
17+
var_dump($test);
18+
19+
try {
20+
$test->b = 4;
21+
} catch (Error $e) {
22+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
23+
}
24+
25+
var_dump($test);
26+
27+
?>
28+
--EXPECT--
29+
object(Test)#2 (2) {
30+
["a"]=>
31+
int(3)
32+
["b"]=>
33+
int(2)
34+
}
35+
Error: Cannot modify readonly property Test::$b
36+
object(Test)#2 (2) {
37+
["a"]=>
38+
int(3)
39+
["b"]=>
40+
int(2)
41+
}

Zend/zend_objects.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ ZEND_API zend_object *zend_objects_clone_obj_with(zend_object *old_object, const
322322
} ZEND_HASH_FOREACH_END();
323323

324324
EG(fake_scope) = old_scope;
325+
326+
/* Lock readonly properties once more. */
327+
if (ZEND_CLASS_HAS_READONLY_PROPS(new_object->ce)) {
328+
for (uint32_t i = 0; i < new_object->ce->default_properties_count; i++) {
329+
zval* prop = OBJ_PROP_NUM(new_object, i);
330+
Z_PROP_FLAG_P(prop) &= ~IS_PROP_REINITABLE;
331+
}
332+
}
325333
}
326334

327335
return new_object;

0 commit comments

Comments
 (0)