From 5d3cf577aad15b119c137a873f468c0614f2eb2e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 11 Jun 2015 19:41:43 +0200 Subject: Make convert_to_* safe with rc>1 This only involves switching zval_dtor to zval_ptr_dtor for arrays and making the convert_to_object for arrays a bit more generic. All the other changes outside zend_operators.c just make use of this new ability (use COPY instead of DUP). What's still missing: Proper references handling. I've seen many convert_to* calls that will break when a reference is used. Also fixes bug #69788. --- Zend/zend_operators.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'Zend/zend_operators.c') diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index aa20bcaf59..a6172179f5 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -209,7 +209,7 @@ try_again: (op) = &(holder); \ break; \ case IS_OBJECT: \ - ZVAL_DUP(&(holder), op); \ + ZVAL_COPY(&(holder), op); \ convert_to_long_base(&(holder), 10); \ if (Z_TYPE(holder) == IS_LONG) { \ (op) = &(holder); \ @@ -312,7 +312,7 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */ break; case IS_ARRAY: tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); - zval_dtor(op); + zval_ptr_dtor(op); ZVAL_LONG(op, tmp); break; case IS_OBJECT: @@ -369,7 +369,7 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */ break; case IS_ARRAY: tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); - zval_dtor(op); + zval_ptr_dtor(op); ZVAL_DOUBLE(op, tmp); break; case IS_OBJECT: @@ -408,7 +408,7 @@ ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */ } } - zval_dtor(op); + zval_ptr_dtor(op); ZVAL_NULL(op); } /* }}} */ @@ -452,7 +452,7 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */ break; case IS_ARRAY: tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); - zval_dtor(op); + zval_ptr_dtor(op); ZVAL_BOOL(op, tmp); break; case IS_OBJECT: @@ -516,7 +516,7 @@ ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{ } case IS_ARRAY: zend_error(E_NOTICE, "Array to string conversion"); - zval_dtor(op); + zval_ptr_dtor(op); ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0)); break; case IS_OBJECT: { @@ -603,14 +603,10 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */ switch (Z_TYPE_P(op)) { case IS_ARRAY: { - HashTable *properties = emalloc(sizeof(HashTable)); - zend_array *arr = Z_ARR_P(op); - - memcpy(properties, Z_ARRVAL_P(op), sizeof(HashTable)); - object_and_properties_init(op, zend_standard_class_def, properties); - if (--GC_REFCOUNT(arr) == 0) { - efree_size(arr, sizeof(zend_array)); - } + zval tmp; + ZVAL_COPY_VALUE(&tmp, op); + SEPARATE_ARRAY(&tmp); + object_and_properties_init(op, zend_standard_class_def, Z_ARR(tmp)); break; } case IS_OBJECT: -- cgit v1.2.1