|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-01-03 12:08 UTC] nikic@php.net
Description:
------------
There are currently a number of places in the engine and library where the properties table is not properly separated. Essentially it's all the cases where get_properties() (or OBJPROP or HASH_OF) is used in a write context.
Two examples (assuming no immutable arrays):
$obj = (object) ['foo' => 1, 'bar' => 2];
foreach ($obj as $val) {
var_dump($val);
$obj->bar = 42;
}
This outputs 1, 1, 42 instead of 1, 42, because the properties table will be separated at the assignment, while it should have been separated at the start of the loop.
$arr = ['foo' => 1, 'bar' => 2];
$obj = (object) $arr;
next($obj);
var_dump(current($arr));
This outputs 2 instead of 1, because next() did not separate the properties HT, so it is still shared with the array.
I'm not sure how we should best fix this. We could always separate in get_properties(), however not all get_properties() uses are in write context. We can't cleanly separate outside get_properties(), as we'd have to assume how the properties are stored. The best option would likely be an extra argument to determine read/write context, but that's not ABI compatible.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 10:00:01 2025 UTC |
For case 1: maybe we should not reset iter->pos if ht is updated(ht != iter->ht). something like: diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 11034fe..c44c689 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -381,7 +381,6 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTab ht->u.v.nIteratorsCount++; } iter->ht = ht; - iter->pos = ht->nInternalPointer; } return iter->pos; } @@ -405,7 +404,6 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval ht->u.v.nIteratorsCount++; } iter->ht = ht; - iter->pos = ht->nInternalPointer; } return iter->pos; } for case 2, maybe we could simple separate the array? thanks