summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_operators.c44
-rw-r--r--ext/spl/spl_heap.c4
-rw-r--r--ext/spl/spl_iterators.c8
-rw-r--r--ext/spl/tests/RegexIterator_with_reference_replacement.phpt19
-rw-r--r--ext/spl/tests/SplHeap_with_by_reference_compare.phpt16
-rw-r--r--ext/standard/array.c10
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);
}