Zend bug? Overloading API in PHP4

php.internals

Rasmus Lerdorf

23 years ago
Did the overloading API in PHP4 actually ever work? I have done some simple stuff with it in the past, but I tried using it for something real today and it is falling over. I have a very simple example extension which illustrates it. See http://lerdorf.com/ovl.tar.gz For the lazy, here is the meat of it. The problem is in my set function which looks like this: int _ovl_property_set(zend_property_reference *prop_ref, zval *value) { zend_llist_element *element = prop_ref->elements_list->head; zval overloaded_property = ((zend_overloaded_element *)(element->data))->element; zval_add_ref(&value); add_property_zval(prop_ref->object, Z_STRVAL(overloaded_property), value); return SUCCESS; } If I do: $obj->foo = array(1,2,3); Then the zval value that gets passed to my set function is messed up. If instead I do: $tmp = array(1,2,3); $obj->foo = $tmp; Then everything is fine. The http://lerdorf.com/ovl.tar.gz tarball has a full self-contained example of the problem if someone wouldn't mind having a look. -Rasmus

Zeev Suraski

23 years ago
At 01:10 16/08/2003, Rasmus Lerdorf wrote:
>Did the overloading API in PHP4 actually ever work?
Yep.
> I have done some >simple stuff with it in the past, but I tried using it for something real >today and it is falling over. I have a very simple example extension >which illustrates it. See http://lerdorf.com/ovl.tar.gz > >For the lazy, here is the meat of it. The problem is in my set function >which looks like this: > >int _ovl_property_set(zend_property_reference *prop_ref, zval *value) { > zend_llist_element *element = prop_ref->elements_list->head; > zval overloaded_property = ((zend_overloaded_element > *)(element->data))->element; > > zval_add_ref(&value); > add_property_zval(prop_ref->object, Z_STRVAL(overloaded_property), > value); > return SUCCESS; >} > >If I do: > > $obj->foo = array(1,2,3); > >Then the zval value that gets passed to my set function is messed up. If >instead I do: > > $tmp = array(1,2,3); > $obj->foo = $tmp; > >Then everything is fine. > >The http://lerdorf.com/ovl.tar.gz tarball has a full self-contained >example of the problem if someone wouldn't mind having a look.
You can't (reliably) connect to zval's that are passed to the setter callback in ZE1, as they're not necessarily reference counted. If you want to retain them, you have to duplicate them (using zval_copy_ctor()). array(1,2,3) is a temporary value that is destroyed regardless of its reference count. Zeev

Rasmus Lerdorf

23 years ago
On Sat, 16 Aug 2003, Zeev Suraski wrote:
> You can't (reliably) connect to zval's that are passed to the setter > callback in ZE1, as they're not necessarily reference counted. If you want > to retain them, you have to duplicate them (using zval_copy_ctor()). > array(1,2,3) is a temporary value that is destroyed regardless of its > reference count.
But where do I copy it? As soon as I enter my _set function before I do anything, the passed zval is bogus. -Rasmus

Rasmus Lerdorf

23 years ago
On Fri, 15 Aug 2003, Rasmus Lerdorf wrote:
> On Sat, 16 Aug 2003, Zeev Suraski wrote: > > You can't (reliably) connect to zval's that are passed to the setter > > callback in ZE1, as they're not necessarily reference counted. If you want > > to retain them, you have to duplicate them (using zval_copy_ctor()). > > array(1,2,3) is a temporary value that is destroyed regardless of its > > reference count. > > But where do I copy it? As soon as I enter my _set function before I do > anything, the passed zval is bogus.
Just to verify this, I tried what I think you meant. My setter now looks like this: int _ovl_property_set(zend_property_reference *prop_ref, zval *value) { zend_llist_element *element = prop_ref->elements_list->head; zval overloaded_property = ((zend_overloaded_element *)(element->data))->element; zval *tmp; tmp = value; zval_copy_ctor(tmp); add_property_zval(prop_ref->object, Z_STRVAL(overloaded_property), tmp); return SUCCESS; } No change. -Rasmus

Zeev Suraski

23 years ago
At 01:50 16/08/2003, Rasmus Lerdorf wrote:
>On Fri, 15 Aug 2003, Rasmus Lerdorf wrote: > > > On Sat, 16 Aug 2003, Zeev Suraski wrote: > > > You can't (reliably) connect to zval's that are passed to the setter > > > callback in ZE1, as they're not necessarily reference counted. If > you want > > > to retain them, you have to duplicate them (using zval_copy_ctor()). > > > array(1,2,3) is a temporary value that is destroyed regardless of its > > > reference count. > > > > But where do I copy it? As soon as I enter my _set function before I do > > anything, the passed zval is bogus. > >Just to verify this, I tried what I think you meant. My setter now looks >like this: > >int _ovl_property_set(zend_property_reference *prop_ref, zval *value) { > zend_llist_element *element = prop_ref->elements_list->head; > zval overloaded_property = ((zend_overloaded_element > *)(element->data))->element; > zval *tmp; > > tmp = value; > zval_copy_ctor(tmp); > add_property_zval(prop_ref->object, Z_STRVAL(overloaded_property), tmp); > return SUCCESS; >} > >No change.
Nope. Try this instead: zval *tmp; ALLOC_ZVAL(tmp); *tmp = *value; zval_copy_ctor(tmp); INIT_PZVAL(tmp); Zeev

Rasmus Lerdorf

23 years ago
On Sat, 16 Aug 2003, Zeev Suraski wrote:
> zval *tmp; > > ALLOC_ZVAL(tmp); > *tmp = *value; > zval_copy_ctor(tmp); > INIT_PZVAL(tmp);
Aha, that makes my little ovl example work. Which means I must be messing up my zval in my much more complex example myself. Thanks. -Rasmus

Zeev Suraski

23 years ago
At 01:38 16/08/2003, Rasmus Lerdorf wrote:
>On Sat, 16 Aug 2003, Zeev Suraski wrote: > > You can't (reliably) connect to zval's that are passed to the setter > > callback in ZE1, as they're not necessarily reference counted. If you want > > to retain them, you have to duplicate them (using zval_copy_ctor()). > > array(1,2,3) is a temporary value that is destroyed regardless of its > > reference count. > >But where do I copy it? As soon as I enter my _set function before I do >anything, the passed zval is bogus.
That doesn't sound right. Are you sure? The zval should be fine at that point, but should be destroyed as soon as your setter returns. Zeev