Skip to content

Commit 07e418a

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Fix phpGH-16261: Reference invariant broken in mb_convert_variables()
2 parents 82d58c4 + 2fe8c4a commit 07e418a

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ PHP NEWS
7777
. Fix GH-16136 (Memory leak in php_ldap_do_modify() when entry is not a
7878
proper dictionary). (Girgias)
7979

80+
- MBString:
81+
. Fixed bug GH-16261 (Reference invariant broken in mb_convert_variables()).
82+
(nielsdos)
83+
8084
- Opcache:
8185
. Fixed bug GH-16009 (Segmentation fault with frameless functions and
8286
undefined CVs). (nielsdos)

ext/mbstring/mbstring.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3770,7 +3770,22 @@ static bool mb_recursive_convert_variable(zval *var, const mbfl_encoding* from_e
37703770

37713771
HashTable *ht = HASH_OF(var);
37723772
if (ht != NULL) {
3773-
ZEND_HASH_FOREACH_VAL_IND(ht, entry) {
3773+
ZEND_HASH_FOREACH_VAL(ht, entry) {
3774+
/* Can be a typed property declaration, in which case we need to remove the reference from the source list.
3775+
* Just using ZEND_TRY_ASSIGN_STRINGL is not sufficient because that would not unwrap the reference
3776+
* and change values through references (see bug #26639). */
3777+
if (Z_TYPE_P(entry) == IS_INDIRECT) {
3778+
ZEND_ASSERT(Z_TYPE_P(var) == IS_OBJECT);
3779+
3780+
entry = Z_INDIRECT_P(entry);
3781+
if (Z_ISREF_P(entry) && Z_TYPE_P(Z_REFVAL_P(entry)) == IS_STRING) {
3782+
zend_property_info *info = zend_get_typed_property_info_for_slot(Z_OBJ_P(var), entry);
3783+
if (info) {
3784+
ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(entry), info);
3785+
}
3786+
}
3787+
}
3788+
37743789
if (mb_recursive_convert_variable(entry, from_encoding, to_encoding)) {
37753790
if (Z_REFCOUNTED_P(var)) {
37763791
Z_UNPROTECT_RECURSION_P(var);

ext/mbstring/tests/gh16261.phpt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
GH-16261 (Reference invariant broken in mb_convert_variables())
3+
--EXTENSIONS--
4+
mbstring
5+
--FILE--
6+
<?php
7+
class Test {
8+
public string $x;
9+
public string $y;
10+
public array $z;
11+
}
12+
$test = new Test;
13+
$ref = "hello";
14+
$ref2 = "world";
15+
$ref3 = [&$ref2];
16+
$test->x =& $ref;
17+
$test->z =& $ref3;
18+
mb_convert_variables("EUC-JP", "Shift_JIS", $test);
19+
20+
class Test2 {
21+
public function __construct(public string $x) {}
22+
}
23+
$test2 = new Test2("foo");
24+
25+
mb_convert_variables("EUC-JP", "Shift_JIS", $test->x);
26+
27+
var_dump($test, $test2);
28+
?>
29+
--EXPECT--
30+
object(Test)#1 (2) {
31+
["x"]=>
32+
string(5) "hello"
33+
["y"]=>
34+
uninitialized(string)
35+
["z"]=>
36+
&array(1) {
37+
[0]=>
38+
string(5) "world"
39+
}
40+
}
41+
object(Test2)#2 (1) {
42+
["x"]=>
43+
string(3) "foo"
44+
}

0 commit comments

Comments
 (0)