Skip to content

Commit 55aa4ec

Browse files
Route dynamic-property fallback through zend_update_property_ex()
Per @arnaudlb's review: zend_std_write_property() skips the object's write_property handler. For internal classes (or user objects that swap handlers at create_object time), that can bypass semantic validation the class expects on property writes. Switch to zend_update_property_ex(scope_ce ?: obj_ce, obj, name, value) which dispatches through the handler, keeping compatibility with overridden write paths. Scope falls back to obj_ce when scope_ce is NULL (stdClass-scoped dynamic prop on a user class).
1 parent 37a5aa3 commit 55aa4ec

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

deepclone.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3346,10 +3346,13 @@ PHP_FUNCTION(deepclone_hydrate)
33463346
RETURN_THROWS();
33473347
}
33483348
} else {
3349-
/* Fallback: dynamic property or unknown name. Matches
3350-
* unserialize(): the engine rejects NUL-prefix names with
3351-
* \Error and accepts NUL-in-middle as raw dynamic props. */
3352-
zend_std_write_property(obj, prop_name, prop_val, NULL);
3349+
/* Fallback: dynamic property or unknown name. Goes through
3350+
* zend_update_property_ex() so any overridden write_property
3351+
* handler (internal classes, extensions overriding default
3352+
* handlers) is respected. Matches unserialize(): the engine
3353+
* rejects NUL-prefix names with \Error and accepts NUL-in-middle
3354+
* as raw dynamic properties. */
3355+
zend_update_property_ex(scope_ce ?: obj_ce, obj, prop_name, prop_val);
33533356
if (UNEXPECTED(EG(exception))) {
33543357
if (prop_name_owned) zend_string_release(prop_name);
33553358
EG(fake_scope) = old_scope;

0 commit comments

Comments
 (0)