]> granicus.if.org Git - php/commitdiff
- Fix issue with destruction of overloaded objects
authorMarcus Boerger <helly@php.net>
Sun, 24 Aug 2008 16:45:50 +0000 (16:45 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 24 Aug 2008 16:45:50 +0000 (16:45 +0000)
# The issue is that we assume default object handlers when calling method
# __destruct(). Now the default handlers might not be compatible with the
# correct handlers which would result in crashes or they simply do cannot
# support everything the object was supposed to do. The latter case will be
# demonstrated in ext/spl/tests/iterator_068.phpt.

Zend/zend_gc.c
Zend/zend_objects.c
Zend/zend_objects_API.c
Zend/zend_objects_API.h

index 76a490b8edf2d359fe486609205b36c938438390..7892c6d027aabe23f281460833167c8d5e4f8adb 100644 (file)
@@ -571,7 +571,7 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
                                        Z_TYPE(p->z) = IS_NULL;
-                                       zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
+                                       zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p->z), Z_OBJ_HT(p->z) TSRMLS_CC);
                                }
                        } else if (Z_TYPE(p->z) == IS_ARRAY) {
                                Z_TYPE(p->z) = IS_NULL;
index afedb57199c2cdc8a632bffba0409a2afd20f44d..4e309770336b52b928af84a6887f8b78c5fc73f5 100644 (file)
@@ -55,6 +55,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
 
        if (destructor) {
                zval *obj;
+               zend_object_store_bucket *obj_bucket;
 
                if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
                        if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -89,7 +90,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
                MAKE_STD_ZVAL(obj);
                Z_TYPE_P(obj) = IS_OBJECT;
                Z_OBJ_HANDLE_P(obj) = handle;
-               Z_OBJ_HT_P(obj) = &std_object_handlers;
+               obj_bucket = &EG(objects_store).object_buckets[handle];
+               if (!obj_bucket->bucket.obj.handlers) {
+                       obj_bucket->bucket.obj.handlers = &std_object_handlers;
+               }
+               Z_OBJ_HT_P(obj) = obj_bucket->bucket.obj.handlers;
                zval_copy_ctor(obj);
 
                /* Make sure that destructors are protected from previously thrown exceptions.
index ec8cd673e47e9716ca1e1a13c8571d207392e5b8..06f0e356aa78b13ab84ad7053a736f1f07b77df0 100644 (file)
@@ -125,8 +125,8 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st
        obj->object = object;
        obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
        obj->free_storage = free_storage;
-
        obj->clone = clone;
+       obj->handlers = NULL;
 
 #if ZEND_DEBUG_OBJECTS
        fprintf(stderr, "Allocated object id #%d\n", handle);
@@ -184,7 +184,7 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) /* {{{ */
        handle = Z_OBJ_HANDLE_P(zobject);
 
        Z_ADDREF_P(zobject);
-       zend_objects_store_del_ref_by_handle(handle TSRMLS_CC);
+       zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
        Z_DELREF_P(zobject);
 
        GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
@@ -194,7 +194,7 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) /* {{{ */
 /*
  * Delete a reference to an objects store entry given the object handle.
  */
-ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) /* {{{ */
+ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */
 {
        struct _store_object *obj;
        int failure = 0;
@@ -215,6 +215,9 @@ ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSR
                                EG(objects_store).object_buckets[handle].destructor_called = 1;
 
                                if (obj->dtor) {
+                                       if (handlers && !obj->handlers) {
+                                               obj->handlers = handlers;
+                                       }
                                        zend_try {
                                                obj->dtor(obj->object, handle TSRMLS_CC);
                                        } zend_catch {
@@ -268,6 +271,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
 
        retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC);
        retval.handlers = Z_OBJ_HT_P(zobject);
+       EG(objects_store).object_buckets[handle].bucket.obj.handlers = retval.handlers;
 
        return retval;
 }
@@ -309,8 +313,10 @@ ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC
 ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC) /* {{{ */
 {
        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
-
-       EG(objects_store).object_buckets[handle].destructor_called = 1;
+       zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
+       
+       obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
+       obj_bucket->destructor_called = 1;
 }
 /* }}} */
 
index 637bb423be41fe32a646955fe26ed6de8f76b902..0bc62bd23f7811f1f7f86343c8bb01330578427a 100644 (file)
@@ -37,6 +37,7 @@ typedef struct _zend_object_store_bucket {
                        zend_objects_store_dtor_t dtor;
                        zend_objects_free_object_storage_t free_storage;
                        zend_objects_store_clone_t clone;
+                       const zend_object_handlers *handlers;
                        zend_uint refcount;
                        gc_root_buffer *buffered;
                } obj;
@@ -66,7 +67,10 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st
 ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC);
 ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC);
 ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC);
-ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC);
+ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC);
+static inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) {
+       zend_objects_store_del_ref_by_handle_ex(handle, NULL TSRMLS_CC);
+}
 ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC);
 ZEND_API int zend_objects_is_destructor_called(zend_object_handle handle TSRMLS_DC);
 ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC);