]> granicus.if.org Git - php/commitdiff
Fixed segfault (Zend/tests/026.phpt now pass)
authorXinchen Hui <laruence@gmail.com>
Thu, 20 Feb 2014 07:39:46 +0000 (15:39 +0800)
committerXinchen Hui <laruence@gmail.com>
Thu, 20 Feb 2014 07:39:46 +0000 (15:39 +0800)
Zend/zend_execute.c
Zend/zend_object_handlers.c
Zend/zend_objects_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 3299c1f6823fe7fd34830a73b3994140be21658a..21efb7fdd2a02044fae383d91a5c7ed110b464d2 100644 (file)
@@ -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 {
index a3a024ba1bcc2e8384188ed6d6e3a30a3a3ff39f..bf688df65f4ed4c6498490bf46f8ddc779b467f7 100644 (file)
@@ -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);
                                }
                        }
                }
index f617e92da6ad690a0da8f2d0bd5bb3a70309bbb8..5bef2d49733900966ecb42c93e7d1ed27729bf3a 100644 (file)
@@ -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);
index dfb53daa84c7702fc546087b83da414c1046c99c..b8868e2a96dae53e7f2e1257d2ffe5d227cad99c 100644 (file)
@@ -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();
index 435bba4e0c4a9aa4b8de4cf98fdc779ccc31e2eb..dc54e0efea933a217acccbb43c116a4da45d91e4 100644 (file)
@@ -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();