[GIT-PULLS] [php-src] PR #23434: [skip ci] Document the closure $this internals change in UPGRADING.INTERNALS
[email protected] (nicolas-grekas)
| Newsgroups | php.git-pulls |
|---|---|
| Message-ID | <[email protected]> |
Pull Request: https://github.com/php/php-src/pull/23434 Author: nicolas-grekas `zend_create_closure()`, `zend_create_fake_closure()` and `zend_create_partial_closure()` take the bound `$this` as a `zend_object*` since fbb2e1f23d6, and `zend_get_closure_this_ptr()` returns one — NULL when the closure is unbound, where it used to return a `zval*` that is `IS_UNDEF` — since 7a5e452f14c. Neither commit added a note to `UPGRADING.INTERNALS`, so this adds one to the "Changed" list of section 1, next to the other signature changes. Worth documenting because the change is silent for extension authors: passing a `zval*` where a `zend_object*` is now expected is only a `-Wincompatible-pointer-types` warning, so an extension still builds and then reads the wrong struct at runtime. Concretely, ext-deepclone built clean-looking against master and segfaulted: ``` zend_hash_index_find_bucket (ht=0x7ffff2c87e61, h=757) zim_DeepClone_HydrationContext_hydrate (deepclone.c:4007) zend_call_known_fcc_ex (fcc->object = 0x7ffff2c87eb9) zend_lazy_object_init (zend_lazy_objects.c:661) ``` Its lazy-object initializer was created with `zend_create_fake_closure(..., &this_zval)`; the engine stored that `zval*` as the closure's `this_ptr` and handed it back as `$this`, so `Z_OBJ_P(ZEND_THIS)` in the initializer dereferenced a zval as an object.