From: Xinchen Hui Date: Thu, 20 Feb 2014 07:39:46 +0000 (+0800) Subject: Fixed segfault (Zend/tests/026.phpt now pass) X-Git-Tag: POST_PHPNG_MERGE~412^2~614 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b917458490ece8d418caee5b6e43db9f7567cb72;p=php Fixed segfault (Zend/tests/026.phpt now pass) --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 3299c1f682..21efb7fdd2 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -754,19 +754,23 @@ static inline void zend_assign_to_object(zval *retval, zval *object, zval *prope if (Z_TYPE_P(object) == IS_NULL || (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) || (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) { - SEPARATE_ZVAL_IF_NOT_REF(object); - Z_ADDREF_P(object); - zend_error(E_WARNING, "Creating default object from empty value"); - if (Z_REFCOUNTED_P(object) && Z_REFCOUNT_P(object) == 1) { - /* object was removed by error handler, nothing to assign to */ - zval_ptr_dtor(object); - if (retval) { - ZVAL_NULL(retval); + if (Z_REFCOUNTED_P(object)) { + SEPARATE_ZVAL_IF_NOT_REF(object); + Z_ADDREF_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (Z_REFCOUNT_P(object) == 1) { + /* object was removed by error handler, nothing to assign to */ + zval_ptr_dtor(object); + if (retval) { + ZVAL_NULL(retval); + } + FREE_OP(free_value); + return; } - FREE_OP(free_value); - return; + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Creating default object from empty value"); } - Z_DELREF_P(object); zval_dtor(object); object_init(object); } else { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index a3a024ba1b..bf688df65f 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -545,38 +545,39 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, c variable_ptr = &zobj->properties_table[property_info->offset]; goto found; } - if (UNEXPECTED(!zobj->properties)) { - variable_ptr = zend_hash_find(zobj->properties, property_info->name); + if (EXPECTED(zobj->properties != NULL)) { + if ((variable_ptr = zend_hash_find(zobj->properties, property_info->name)) != NULL) { found: - /* if we already have this value there, we don't actually need to do anything */ - if (EXPECTED(variable_ptr != value)) { - /* if we are assigning reference, we shouldn't move it, but instead assign variable - to the same pointer */ - if (Z_ISREF_P(variable_ptr)) { - zval garbage; - - ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */ - - /* To check: can't *variable_ptr be some system variable like error_zval here? */ - ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value); - if (Z_REFCOUNT_P(value) > 0) { - zval_copy_ctor(Z_REFVAL_P(variable_ptr)); - } - zval_dtor(&garbage); - } else { - zval garbage; + /* if we already have this value there, we don't actually need to do anything */ + if (EXPECTED(variable_ptr != value)) { + /* if we are assigning reference, we shouldn't move it, but instead assign variable + to the same pointer */ + if (Z_ISREF_P(variable_ptr)) { + zval garbage; + + ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */ + + /* To check: can't *variable_ptr be some system variable like error_zval here? */ + ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value); + if (Z_REFCOUNT_P(value) > 0) { + zval_copy_ctor(Z_REFVAL_P(variable_ptr)); + } + zval_dtor(&garbage); + } else { + zval garbage; - ZVAL_COPY_VALUE(&garbage, variable_ptr); + ZVAL_COPY_VALUE(&garbage, variable_ptr); - /* if we assign referenced variable, we should separate it */ - if (IS_REFCOUNTED(Z_TYPE_P(value))) { - Z_ADDREF_P(value); - if (Z_ISREF_P(value)) { - SEPARATE_ZVAL(value); + /* if we assign referenced variable, we should separate it */ + if (IS_REFCOUNTED(Z_TYPE_P(value))) { + Z_ADDREF_P(value); + if (Z_ISREF_P(value)) { + SEPARATE_ZVAL(value); + } } + ZVAL_COPY_VALUE(variable_ptr, value); + zval_ptr_dtor(&garbage); } - ZVAL_COPY_VALUE(variable_ptr, value); - zval_ptr_dtor(&garbage); } } } diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index f617e92da6..5bef2d4973 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -129,7 +129,7 @@ ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */ */ if (EG(objects_store).object_buckets && IS_VALID(EG(objects_store).object_buckets[object->handle])) { - if (object->gc.refcount == 0) { + if (object->gc.refcount == 1) { int failure = 0; if (!(object->gc.u.v.flags & IS_OBJ_DESTRUCTOR_CALLED)) { @@ -146,7 +146,7 @@ ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */ } } - if (object->gc.refcount == 0) { + if (object->gc.refcount == 1) { zend_uint handle = object->handle; //??? GC_REMOVE_ZOBJ_FROM_BUFFER(obj); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index dfb53daa84..b8868e2a96 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5208,11 +5208,11 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) SAVE_OPLINE(); var_ptr = EX_VAR(opline->op1.var); - if (Z_TYPE_P(var_ptr) != IS_OBJECT && - !Z_ISREF_P(var_ptr) && - Z_REFCOUNT_P(var_ptr) > 1) { - - Z_DELREF_P(var_ptr); + if (Z_TYPE_P(var_ptr) != IS_OBJECT && !Z_ISREF_P(var_ptr)) { + if (Z_REFCOUNTED_P(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { + Z_DELREF_P(var_ptr); + } ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); } ZEND_VM_NEXT_OPCODE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 435bba4e0c..dc54e0efea 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -20932,11 +20932,11 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); var_ptr = EX_VAR(opline->op1.var); - if (Z_TYPE_P(var_ptr) != IS_OBJECT && - !Z_ISREF_P(var_ptr) && - Z_REFCOUNT_P(var_ptr) > 1) { - - Z_DELREF_P(var_ptr); + if (Z_TYPE_P(var_ptr) != IS_OBJECT && !Z_ISREF_P(var_ptr)) { + if (Z_REFCOUNTED_P(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { + Z_DELREF_P(var_ptr); + } ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); } ZEND_VM_NEXT_OPCODE();