summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-07-17 14:50:22 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-07-17 14:50:22 +0200
commit0c28b47154d7357ea1f565ac42371df2a5443acc (patch)
treed8846b1a58a4e06d5fe0c59184f94207be6dc0a2
parentbc6979b79e1ee9b7de7efa84a938a8be49f91276 (diff)
downloadphp-git-0c28b47154d7357ea1f565ac42371df2a5443acc.tar.gz
Fixed bug #79839
Add reference type sources in array_walk.
-rw-r--r--NEWS1
-rw-r--r--ext/standard/array.c10
-rw-r--r--ext/standard/tests/array/bug79839.phpt26
3 files changed, 37 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 87ba3835bd..95f211afba 100644
--- a/NEWS
+++ b/NEWS
@@ -49,6 +49,7 @@ PHP NEWS
. Fixed bug #70362 (Can't copy() large 'data://' with open_basedir). (cmb)
. Fixed bug #78008 (dns_check_record() always return true on Alpine).
(Andy Postnikov)
+ . Fixed bug #79839 (array_walk() does not respect property types). (Nikita)
09 Jul 2020, PHP 7.4.8
diff --git a/ext/standard/array.c b/ext/standard/array.c
index ec0890478a..4ae93733df 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1383,6 +1383,16 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
zend_hash_move_forward_ex(target_hash, &pos);
continue;
}
+
+ /* Add type source for property references. */
+ if (Z_TYPE_P(zv) != IS_REFERENCE && Z_TYPE_P(array) == IS_OBJECT) {
+ zend_property_info *prop_info =
+ zend_get_typed_property_info_for_slot(Z_OBJ_P(array), zv);
+ if (prop_info) {
+ ZVAL_NEW_REF(zv, zv);
+ ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(zv), prop_info);
+ }
+ }
}
/* Ensure the value is a reference. Otherwise the location of the value may be freed. */
diff --git a/ext/standard/tests/array/bug79839.phpt b/ext/standard/tests/array/bug79839.phpt
new file mode 100644
index 0000000000..901be9c8de
--- /dev/null
+++ b/ext/standard/tests/array/bug79839.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #79839: array_walk() does not respect property types
+--FILE--
+<?php
+
+class Test {
+ public int $prop = 42;
+}
+
+$test = new Test;
+try {
+ array_walk($test, function(&$ref) {
+ $ref = []; // Should throw
+ });
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($test);
+
+?>
+--EXPECT--
+Cannot assign array to reference held by property Test::$prop of type int
+object(Test)#1 (1) {
+ ["prop"]=>
+ &int(42)
+}