mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Don't overload get_properties for ArrayObject
Instead overload get_properties_for for a few specific cases such as array casts. This resolves the issue where ArrayObject get_properties may violate engine invariants in some cases.
This commit is contained in:
parent
1270e5008a
commit
a5fa51afbb
6 changed files with 105 additions and 56 deletions
|
@ -14,12 +14,6 @@ print_r($reflObj->getProperties(ReflectionProperty::IS_PUBLIC));
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
Array
|
Array
|
||||||
(
|
(
|
||||||
[0] => ReflectionProperty Object
|
|
||||||
(
|
|
||||||
[name] => test
|
|
||||||
[class] => ArrayObject
|
|
||||||
)
|
|
||||||
|
|
||||||
)
|
)
|
||||||
Array
|
Array
|
||||||
(
|
(
|
||||||
|
|
|
@ -807,18 +807,40 @@ SPL_METHOD(Array, getArrayCopy)
|
||||||
RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern)));
|
RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern)));
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
static HashTable *spl_array_get_properties(zval *object) /* {{{ */
|
static HashTable *spl_array_get_properties_for(zval *object, zend_prop_purpose purpose) /* {{{ */
|
||||||
{
|
{
|
||||||
spl_array_object *intern = Z_SPLARRAY_P(object);
|
spl_array_object *intern = Z_SPLARRAY_P(object);
|
||||||
|
HashTable *ht;
|
||||||
|
zend_bool dup;
|
||||||
|
|
||||||
if (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) {
|
if (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) {
|
||||||
if (!intern->std.properties) {
|
return zend_std_get_properties_for(object, purpose);
|
||||||
rebuild_object_properties(&intern->std);
|
|
||||||
}
|
|
||||||
return intern->std.properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return spl_array_get_hash_table(intern);
|
/* We are supposed to be the only owner of the internal hashtable.
|
||||||
|
* The "dup" flag decides whether this is a "long-term" use where
|
||||||
|
* we need to duplicate, or a "temporary" one, where we can expect
|
||||||
|
* that no operations on the ArrayObject will be performed in the
|
||||||
|
* meantime. */
|
||||||
|
switch (purpose) {
|
||||||
|
case ZEND_PROP_PURPOSE_ARRAY_CAST:
|
||||||
|
dup = 1;
|
||||||
|
break;
|
||||||
|
case ZEND_PROP_PURPOSE_VAR_EXPORT:
|
||||||
|
case ZEND_PROP_PURPOSE_JSON:
|
||||||
|
dup = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return zend_std_get_properties_for(object, purpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
ht = spl_array_get_hash_table(intern);
|
||||||
|
if (dup) {
|
||||||
|
ht = zend_array_dup(ht);
|
||||||
|
} else {
|
||||||
|
GC_ADDREF(ht);
|
||||||
|
}
|
||||||
|
return ht;
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */
|
static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */
|
||||||
|
@ -2013,7 +2035,7 @@ PHP_MINIT_FUNCTION(spl_array)
|
||||||
spl_handler_ArrayObject.has_dimension = spl_array_has_dimension;
|
spl_handler_ArrayObject.has_dimension = spl_array_has_dimension;
|
||||||
spl_handler_ArrayObject.count_elements = spl_array_object_count_elements;
|
spl_handler_ArrayObject.count_elements = spl_array_object_count_elements;
|
||||||
|
|
||||||
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
|
spl_handler_ArrayObject.get_properties_for = spl_array_get_properties_for;
|
||||||
spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info;
|
spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info;
|
||||||
spl_handler_ArrayObject.get_gc = spl_array_get_gc;
|
spl_handler_ArrayObject.get_gc = spl_array_get_gc;
|
||||||
spl_handler_ArrayObject.read_property = spl_array_read_property;
|
spl_handler_ArrayObject.read_property = spl_array_read_property;
|
||||||
|
|
30
ext/spl/tests/ArrayObject_get_object_vars.phpt
Normal file
30
ext/spl/tests/ArrayObject_get_object_vars.phpt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
--TEST--
|
||||||
|
get_object_vars() on ArrayObject works on the properties of the ArrayObject itself
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public $test;
|
||||||
|
public $test2;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AO extends ArrayObject {
|
||||||
|
private $test;
|
||||||
|
|
||||||
|
public function getObjectVars() {
|
||||||
|
return get_object_vars($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ao = new AO(new Test);
|
||||||
|
var_dump(get_object_vars($ao));
|
||||||
|
var_dump($ao->getObjectVars());
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
array(1) {
|
||||||
|
["test"]=>
|
||||||
|
NULL
|
||||||
|
}
|
|
@ -139,13 +139,17 @@ array(3) {
|
||||||
["Flags"]=>
|
["Flags"]=>
|
||||||
int(0)
|
int(0)
|
||||||
["OVars"]=>
|
["OVars"]=>
|
||||||
array(3) {
|
array(5) {
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
["a"]=>
|
|
||||||
int(25)
|
|
||||||
["pub1"]=>
|
["pub1"]=>
|
||||||
int(42)
|
int(1)
|
||||||
|
["pro1"]=>
|
||||||
|
int(2)
|
||||||
|
["pri1"]=>
|
||||||
|
int(3)
|
||||||
|
["imp1"]=>
|
||||||
|
int(4)
|
||||||
|
["dyn1"]=>
|
||||||
|
int(5)
|
||||||
}
|
}
|
||||||
["$this"]=>
|
["$this"]=>
|
||||||
object(ArrayObjectEx)#%d (6) {
|
object(ArrayObjectEx)#%d (6) {
|
||||||
|
@ -178,13 +182,17 @@ array(3) {
|
||||||
["Flags"]=>
|
["Flags"]=>
|
||||||
int(0)
|
int(0)
|
||||||
["OVars"]=>
|
["OVars"]=>
|
||||||
array(3) {
|
array(5) {
|
||||||
[0]=>
|
["pub2"]=>
|
||||||
int(1)
|
int(1)
|
||||||
["a"]=>
|
["pro2"]=>
|
||||||
int(25)
|
int(2)
|
||||||
["pub1"]=>
|
["pri2"]=>
|
||||||
int(42)
|
int(3)
|
||||||
|
["imp2"]=>
|
||||||
|
int(4)
|
||||||
|
["dyn2"]=>
|
||||||
|
int(5)
|
||||||
}
|
}
|
||||||
["$this"]=>
|
["$this"]=>
|
||||||
object(ArrayIteratorEx)#%d (6) {
|
object(ArrayIteratorEx)#%d (6) {
|
||||||
|
@ -242,13 +250,17 @@ array(3) {
|
||||||
["Flags"]=>
|
["Flags"]=>
|
||||||
int(0)
|
int(0)
|
||||||
["OVars"]=>
|
["OVars"]=>
|
||||||
array(3) {
|
array(5) {
|
||||||
[0]=>
|
["pub2"]=>
|
||||||
int(1)
|
int(1)
|
||||||
["a"]=>
|
["pro2"]=>
|
||||||
int(25)
|
int(2)
|
||||||
["pub1"]=>
|
["pri2"]=>
|
||||||
int(42)
|
int(3)
|
||||||
|
["imp2"]=>
|
||||||
|
int(4)
|
||||||
|
["dyn2"]=>
|
||||||
|
int(5)
|
||||||
}
|
}
|
||||||
["$this"]=>
|
["$this"]=>
|
||||||
object(ArrayIteratorEx)#%d (6) {
|
object(ArrayIteratorEx)#%d (6) {
|
||||||
|
@ -541,14 +553,16 @@ array(3) {
|
||||||
["Flags"]=>
|
["Flags"]=>
|
||||||
int(0)
|
int(0)
|
||||||
["OVars"]=>
|
["OVars"]=>
|
||||||
array(4) {
|
array(5) {
|
||||||
["pub1"]=>
|
["pub2"]=>
|
||||||
int(1)
|
int(1)
|
||||||
["pro1"]=>
|
["pro2"]=>
|
||||||
int(2)
|
int(2)
|
||||||
["imp1"]=>
|
["pri2"]=>
|
||||||
|
int(3)
|
||||||
|
["imp2"]=>
|
||||||
int(4)
|
int(4)
|
||||||
["dyn1"]=>
|
["dyn2"]=>
|
||||||
int(5)
|
int(5)
|
||||||
}
|
}
|
||||||
["$this"]=>
|
["$this"]=>
|
||||||
|
@ -598,14 +612,16 @@ array(3) {
|
||||||
["Flags"]=>
|
["Flags"]=>
|
||||||
int(0)
|
int(0)
|
||||||
["OVars"]=>
|
["OVars"]=>
|
||||||
array(4) {
|
array(5) {
|
||||||
["pub1"]=>
|
["pub2"]=>
|
||||||
int(1)
|
int(1)
|
||||||
["pro1"]=>
|
["pro2"]=>
|
||||||
int(2)
|
int(2)
|
||||||
["imp1"]=>
|
["pri2"]=>
|
||||||
|
int(3)
|
||||||
|
["imp2"]=>
|
||||||
int(4)
|
int(4)
|
||||||
["dyn1"]=>
|
["dyn2"]=>
|
||||||
int(5)
|
int(5)
|
||||||
}
|
}
|
||||||
["$this"]=>
|
["$this"]=>
|
||||||
|
|
|
@ -12,7 +12,7 @@ var_dump(isset($b['no_exists'])); //false
|
||||||
var_dump(empty($b['b'])); //true
|
var_dump(empty($b['b'])); //true
|
||||||
var_dump(empty($b[37])); //true
|
var_dump(empty($b[37])); //true
|
||||||
|
|
||||||
var_dump(array_key_exists('b', $b)); //true
|
var_dump(array_key_exists('b', $b)); //false
|
||||||
var_dump($b['b']);
|
var_dump($b['b']);
|
||||||
|
|
||||||
$a = array('b' => '', 37 => false);
|
$a = array('b' => '', 37 => false);
|
||||||
|
@ -31,7 +31,7 @@ bool(false)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(false)
|
||||||
NULL
|
NULL
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Ensure that ArrayObject acts like an array
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$a = new ArrayObject;
|
|
||||||
$a['foo'] = 'bar';
|
|
||||||
echo reset($a);
|
|
||||||
echo count($a);
|
|
||||||
echo current($a);
|
|
||||||
?>
|
|
||||||
--EXPECT--
|
|
||||||
bar1bar
|
|
Loading…
Add table
Add a link
Reference in a new issue