From: Nikita Popov Date: Wed, 24 Feb 2016 18:08:18 +0000 (+0100) Subject: Fix AO object properties separation X-Git-Tag: php-7.0.5RC1~60 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0aa716381643c2746ddef019681e762d4e3f4233;p=php Fix AO object properties separation --- diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 2de985bd22..070df29852 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -83,6 +83,7 @@ static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { #define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv))) static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ + //??? TODO: Delay duplication for arrays; only duplicate for write operations if (intern->ar_flags & SPL_ARRAY_IS_SELF) { if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -91,8 +92,19 @@ static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* } else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) { spl_array_object *other = Z_SPLARRAY_P(&intern->array); return spl_array_get_hash_table(other); + } else if (Z_TYPE(intern->array) == IS_ARRAY) { + return Z_ARRVAL(intern->array); } else { - return HASH_OF(&intern->array); + zend_object *obj = Z_OBJ(intern->array); + if (!obj->properties) { + rebuild_object_properties(obj); + } else if (GC_REFCOUNT(obj->properties) > 1) { + if (EXPECTED(!(GC_FLAGS(obj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(obj->properties)--; + } + obj->properties = zend_array_dup(obj->properties); + } + return obj->properties; } } /* }}} */ @@ -1107,13 +1119,6 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar ZVAL_UNDEF(&intern->array); zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_P(array)->name, intern->std.ce->name); } - //??? TODO: try to avoid array duplication - if (Z_OBJ_P(array)->properties && GC_REFCOUNT(Z_OBJ_P(array)->properties) > 1) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_REFCOUNT(Z_OBJ_P(array)->properties)--; - } - Z_OBJ_P(array)->properties = zend_array_dup(Z_OBJ_P(array)->properties); - } ZVAL_COPY(&intern->array, array); } } diff --git a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt new file mode 100644 index 0000000000..24c247cabd --- /dev/null +++ b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt @@ -0,0 +1,19 @@ +--TEST-- +Modifications to ArrayObjects should not affect shared properties tables +--FILE-- + 1, 'b' => 2]; +$ao = new ArrayObject($obj); +$arr = (array) $obj; +$ao['a'] = 42; +var_dump($arr); + +?> +--EXPECT-- +array(2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +}