diff options
-rw-r--r-- | Zend/zend_operators.c | 44 | ||||
-rw-r--r-- | ext/spl/spl_heap.c | 4 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 8 | ||||
-rw-r--r-- | ext/spl/tests/RegexIterator_with_reference_replacement.phpt | 19 | ||||
-rw-r--r-- | ext/spl/tests/SplHeap_with_by_reference_compare.phpt | 16 | ||||
-rw-r--r-- | ext/standard/array.c | 10 |
6 files changed, 80 insertions, 21 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 3176cb505b..d7d2591382 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -135,17 +135,23 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{ } /* }}} */ +static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */ +{ + if (Z_REFCOUNT_P(op) == 1) { + ZVAL_UNREF(op); + } else { + Z_DELREF_P(op); + ZVAL_COPY(op, Z_REFVAL_P(op)); + } +} +/* }}} */ + ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ { try_again: switch (Z_TYPE_P(op)) { case IS_REFERENCE: - if (Z_REFCOUNT_P(op) == 1) { - ZVAL_UNREF(op); - } else { - Z_DELREF_P(op); - ZVAL_COPY(op, Z_REFVAL_P(op)); - } + zend_unwrap_reference(op); goto try_again; case IS_STRING: { @@ -284,6 +290,7 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */ { zend_long tmp; +try_again: switch (Z_TYPE_P(op)) { case IS_NULL: case IS_FALSE: @@ -331,6 +338,9 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */ } return; } + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; EMPTY_SWITCH_DEFAULT_CASE() } } @@ -340,6 +350,7 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */ { double tmp; +try_again: switch (Z_TYPE_P(op)) { case IS_NULL: case IS_FALSE: @@ -388,6 +399,9 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */ } break; } + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; EMPTY_SWITCH_DEFAULT_CASE() } } @@ -417,6 +431,7 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */ { int tmp; +try_again: switch (Z_TYPE_P(op)) { case IS_FALSE: case IS_TRUE: @@ -469,6 +484,9 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */ } break; } + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; EMPTY_SWITCH_DEFAULT_CASE() } } @@ -482,6 +500,7 @@ ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* { ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */ { +try_again: switch (Z_TYPE_P(op)) { case IS_UNDEF: case IS_NULL: @@ -534,6 +553,9 @@ ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{ } break; } + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; EMPTY_SWITCH_DEFAULT_CASE() } } @@ -553,7 +575,7 @@ static void convert_scalar_to_array(zval *op) /* {{{ */ ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */ { - +try_again: switch (Z_TYPE_P(op)) { case IS_ARRAY: break; @@ -590,6 +612,9 @@ ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */ ZVAL_NEW_ARR(op); zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0); break; + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; default: convert_scalar_to_array(op); break; @@ -599,7 +624,7 @@ ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */ { - +try_again: switch (Z_TYPE_P(op)) { case IS_ARRAY: { @@ -614,6 +639,9 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */ case IS_NULL: object_init(op); break; + case IS_REFERENCE: + zend_unwrap_reference(op); + goto try_again; default: { zval tmp; ZVAL_COPY_VALUE(&tmp, op); diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index c4857663e7..1d8cde25fa 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -112,9 +112,7 @@ static int spl_ptr_heap_cmp_cb_helper(zval *object, spl_heap_object *heap_object return FAILURE; } - convert_to_long(&zresult); - *result = Z_LVAL(zresult); - + *result = zval_get_long(&zresult); zval_ptr_dtor(&zresult); return SUCCESS; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index aa0854ab78..ed325a1880 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1065,12 +1065,12 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *objec * without __toString is converted to string is converted into an exception. */ zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); if (data) { - RETVAL_ZVAL(data, 1, 0); - if (Z_TYPE_P(return_value) == IS_ARRAY) { - zval_ptr_dtor(return_value); + ZVAL_DEREF(data); + if (Z_TYPE_P(data) == IS_ARRAY) { ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1); } else { - convert_to_string_ex(return_value); + ZVAL_COPY(return_value, data); + convert_to_string(return_value); } } zend_restore_error_handling(&error_handling); diff --git a/ext/spl/tests/RegexIterator_with_reference_replacement.phpt b/ext/spl/tests/RegexIterator_with_reference_replacement.phpt new file mode 100644 index 0000000000..18b3ef9089 --- /dev/null +++ b/ext/spl/tests/RegexIterator_with_reference_replacement.phpt @@ -0,0 +1,19 @@ +--TEST-- +RegexIterator with $replacement being a reference +--FILE-- +<?php +$a = new ArrayIterator(array('test1', 'test2', 'test3')); +$i = new RegexIterator($a, '/^(test)(\d+)/', RegexIterator::REPLACE); +$r = '$2:$1'; +$i->replacement =& $r; +var_dump(iterator_to_array($i)); +?> +--EXPECT-- +array(3) { + [0]=> + string(6) "1:test" + [1]=> + string(6) "2:test" + [2]=> + string(6) "3:test" +} diff --git a/ext/spl/tests/SplHeap_with_by_reference_compare.phpt b/ext/spl/tests/SplHeap_with_by_reference_compare.phpt new file mode 100644 index 0000000000..b7b7b6d747 --- /dev/null +++ b/ext/spl/tests/SplHeap_with_by_reference_compare.phpt @@ -0,0 +1,16 @@ +--TEST-- +SplHeap using a compare function returning by-reference +--FILE-- +<?php +class Heap extends SplMinHeap { + public function &compare($a, $b) { + return $a; + } +} +$h = new Heap; +$h->insert(0); +$h->insert(0); +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/standard/array.c b/ext/standard/array.c index b05900656d..527f6a3df1 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3099,17 +3099,15 @@ PHP_FUNCTION(array_column) zkeyval = zend_hash_index_find(ht, Z_LVAL_P(zkey)); } - if (Z_REFCOUNTED_P(zcolval)) { - Z_ADDREF_P(zcolval); - } + Z_TRY_ADDREF_P(zcolval); if (zkeyval && Z_TYPE_P(zkeyval) == IS_STRING) { zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(zkeyval), zcolval); } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_LONG) { add_index_zval(return_value, Z_LVAL_P(zkeyval), zcolval); } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_OBJECT) { - SEPARATE_ZVAL(zkeyval); - convert_to_string(zkeyval); - zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(zkeyval), zcolval); + zend_string *key = zval_get_string(zkeyval); + zend_symtable_update(Z_ARRVAL_P(return_value), key, zcolval); + zend_string_release(key); } else { add_next_index_zval(return_value, zcolval); } |