Skip to content

Commit

Permalink
Indirect support for fetching address
Browse files Browse the repository at this point in the history
  • Loading branch information
Girgias committed Jun 1, 2024
1 parent d975033 commit b99c40a
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ foreach ($offsets as $offset) {
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
&& !preg_match($EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX, $varOutput)
&& $varOutput !== EXPECTED_OUTPUT_NULL_OFFSET
&& $varOutput !== EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS
) {
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_ArrayObject_container_{$failuresNb}.txt", $varOutput);
Expand Down
12 changes: 11 additions & 1 deletion Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -2765,12 +2765,22 @@ static zend_never_inline void zend_fetch_object_dimension_address(zval *result,
ZVAL_UNDEF(result);
goto clean_up;
}
if (!Z_ISREF_P(retval) && Z_TYPE_P(retval) != IS_OBJECT) {
if (
!Z_ISREF_P(retval)
&& Z_TYPE_P(retval) != IS_OBJECT
/* Indirect support is needed for supporting $ArrayObject[$i] = &$var; constructs */
&& Z_TYPE_P(retval) != IS_INDIRECT
) {
zend_class_entry *ce = obj->ce;
zend_throw_error(NULL, "%s::%s() must return a reference type",
ZSTR_VAL(ce->name), offset ? "offsetFetch" : "fetchAppend");
ZVAL_UNDEF(result);
goto clean_up;
} else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
ZVAL_UNREF(retval);
}
if (result != retval) {
ZVAL_INDIRECT(result, retval);
}
} else {
zend_use_object_as_array(obj);
Expand Down
23 changes: 5 additions & 18 deletions ext/spl/spl_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,13 @@ static zval *spl_array_read_dimension_ex(zend_object *object, zval *offset, int
//}

if (type == BP_VAR_W) {
if (Z_TYPE_P(ret) == IS_OBJECT) {
ZVAL_COPY(rv, ret);
} else {
ZVAL_NEW_REF(ret, ret);
zend_reference *ref = Z_REF_P(ret);
GC_ADDREF(ref);
ZVAL_REF(rv, ref);
}
ZVAL_NEW_REF(ret, ret);
return ret;
} else {
ZVAL_COPY_DEREF(rv, ret);
return rv;
}

return rv;
} /* }}} */

static zval *spl_array_read_dimension(zend_object *object, zval *offset, zval *rv) /* {{{ */
Expand Down Expand Up @@ -511,20 +505,13 @@ static zval* spl_array_fetch_append(zend_object *object, zval *rv)
ZVAL_NULL(&dummy);
zval *ret = zend_hash_next_index_insert(ht, &dummy);

if (Z_TYPE_P(ret) == IS_OBJECT) {
ZVAL_COPY(rv, ret);
} else {
ZVAL_NEW_REF(ret, ret);
zend_reference *ref = Z_REF_P(ret);
GC_ADDREF(ref);
ZVAL_REF(rv, ref);
}
ZVAL_NEW_REF(ret, ret);

if (refcount) {
spl_array_set_refcount(intern->is_child, ht, refcount);
}

return rv;
return ret;
}

static void spl_array_unset_dimension(zend_object *object, zval *offset) /* {{{ */
Expand Down
44 changes: 25 additions & 19 deletions ext/spl/tests/ArrayObject/indirect_assign_reference_to_offset.phpt
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
--TEST--
Bug #73686 (Adding settype()ed values to ArrayObject results in references)
Setting indirections must work for ArrayObject
--FILE--
<?php

$ao = new ArrayObject;
// Based on test file for Bug #73686

echo "Using array\n";
$a = [];
foreach ([1, 2, 3] as $i => $var)
{
settype($var, 'string');
$ao[$i] = $var;
$a[$i] = &$var;
}
var_dump($ao);
$a[] = &$var;
var_dump($a);

echo "Using ArrayObject\n";
$ao = new ArrayObject;

foreach ([1, 2, 3] as $i => $var)
{
$ao[$i] = &$var;
}
$ao[] = &$var;
var_dump($ao);
?>
--EXPECTF--
object(ArrayObject)#%d (1) {
["storage":"ArrayObject":private]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
}
--EXPECT--
Using array
array(4) {
[0]=>
&int(3)
[1]=>
&int(3)
[2]=>
&int(3)
[3]=>
&int(3)
}
object(ArrayObject)#%d (1) {
Using ArrayObject
object(ArrayObject)#1 (1) {
["storage":"ArrayObject":private]=>
array(3) {
array(4) {
[0]=>
&int(3)
[1]=>
&int(3)
[2]=>
&int(3)
[3]=>
&int(3)
}
}
17 changes: 12 additions & 5 deletions ext/spl/tests/iterator_035.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ $a = new ArrayIterator();
$a[] = $tmp;
$a[] = &$tmp;

var_dump($a);
echo "Done\n";
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot assign by reference to an array dimension of an object in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
--EXPECT--
object(ArrayIterator)#1 (1) {
["storage":"ArrayIterator":private]=>
array(2) {
[0]=>
int(1)
[1]=>
&int(1)
}
}
Done

0 comments on commit b99c40a

Please sign in to comment.