From ac5c0c26f503045de7b07796b033ddc23d3176fe Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 23 Aug 2022 18:58:54 +0200 Subject: [PATCH] Add load_mangled_object_vars(), the inverse of get_mangled_object_vars() --- Zend/tests/load_mangled_object_vars.phpt | 84 ++++++++++++++++++++++++ Zend/zend_builtin_functions.c | 17 ++++- Zend/zend_builtin_functions.stub.php | 2 + Zend/zend_builtin_functions_arginfo.h | 9 ++- 4 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/load_mangled_object_vars.phpt diff --git a/Zend/tests/load_mangled_object_vars.phpt b/Zend/tests/load_mangled_object_vars.phpt new file mode 100644 index 0000000000000..48dcda89b13ac --- /dev/null +++ b/Zend/tests/load_mangled_object_vars.phpt @@ -0,0 +1,84 @@ +--TEST-- +load_mangled_object_vars() function +--FILE-- +dyn = 5; +$obj->{"6"} = 6; + +$vars = get_mangled_object_vars($obj); + +$obj2 = new B; +$obj2->pub = 7; +load_mangled_object_vars($obj2, $vars); + +$vars2 = (array) $obj2; +var_dump($vars2 === $vars); + +#[AllowDynamicProperties] +class AO extends ArrayObject { + private $priv = 1; +} + +$ao = new AO(['x' => 'y']); +$ao->dyn = 2; +$vars = get_mangled_object_vars($ao); + +$ao2 = new AO(); +load_mangled_object_vars($ao2, $vars); + +$vars2 = get_mangled_object_vars($ao2); +var_dump($vars2 === $vars); + +class RO { + public function __construct(public readonly int $ro = 123) + { + } +} + +$ro = new RO; +load_mangled_object_vars($ro, []); +var_dump($ro); + +load_mangled_object_vars($ro, ['ro' => 'abc']); +var_dump($ro); + +#[AllowDynamicProperties] +class DYN { + public function __set($name, $value) + { + $this->data[$name] = $value; + } +} + +$dyn = new DYN; +load_mangled_object_vars($dyn, ['abc' => 123]); +var_dump((array) $dyn); + +?> +--EXPECTF-- +bool(true) +bool(true) +object(RO)#%d (1) { + ["ro"]=> + int(123) +} +object(RO)#%d (1) { + ["ro"]=> + int(234) +} +array(1) { + ["abc"]=> + int(123) +} diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 8813fa9788a97..981bdd0ff674f 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -801,7 +801,7 @@ ZEND_FUNCTION(get_object_vars) } /* }}} */ -/* {{{ Returns an array of mangled object properties. Does not respect property visibility. */ +/* {{{ Returns an array of mangled object properties. Does not respect property visibility and does not call magic methods. */ ZEND_FUNCTION(get_mangled_object_vars) { zend_object *obj; @@ -825,6 +825,21 @@ ZEND_FUNCTION(get_mangled_object_vars) } /* }}} */ +/* {{{ Loads an array of mangled object properties. Does not respect property visibility and does not call magic methods. */ +ZEND_FUNCTION(load_mangled_object_vars) +{ + zend_object *obj; + HashTable *vars; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJ(obj) + Z_PARAM_ARRAY_HT(vars) + ZEND_PARSE_PARAMETERS_END(); + + object_properties_load(obj, vars); +} +/* }}} */ + /* {{{ Returns an array of method names for class or class instance. */ ZEND_FUNCTION(get_class_methods) { diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index ca04719742c54..05d81f70de225 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -59,6 +59,8 @@ function get_object_vars(object $object): array {} function get_mangled_object_vars(object $object): array {} +function load_mangled_object_vars(object $object, array $vars): void {} + /** * @return array * @refcount 1 diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 838084418871c..aa02a4a6106c3 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 80355bb52d643177e3a661a515d9ea915bd1e2fc */ + * Stub hash: 7b548f713f2250c5af982305c869d43376663b3a */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -79,6 +79,11 @@ ZEND_END_ARG_INFO() #define arginfo_get_mangled_object_vars arginfo_get_object_vars +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_load_mangled_object_vars, 0, 2, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) + ZEND_ARG_TYPE_INFO(0, vars, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_class_methods, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, object_or_class, MAY_BE_OBJECT|MAY_BE_STRING, NULL) ZEND_END_ARG_INFO() @@ -238,6 +243,7 @@ ZEND_FUNCTION(is_a); ZEND_FUNCTION(get_class_vars); ZEND_FUNCTION(get_object_vars); ZEND_FUNCTION(get_mangled_object_vars); +ZEND_FUNCTION(load_mangled_object_vars); ZEND_FUNCTION(get_class_methods); ZEND_FUNCTION(method_exists); ZEND_FUNCTION(property_exists); @@ -299,6 +305,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(get_class_vars, arginfo_get_class_vars) ZEND_FE(get_object_vars, arginfo_get_object_vars) ZEND_FE(get_mangled_object_vars, arginfo_get_mangled_object_vars) + ZEND_FE(load_mangled_object_vars, arginfo_load_mangled_object_vars) ZEND_FE(get_class_methods, arginfo_get_class_methods) ZEND_FE(method_exists, arginfo_method_exists) ZEND_FE(property_exists, arginfo_property_exists)