diff options
author | Nikita Popov <nikic@php.net> | 2015-12-17 22:11:08 +0100 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2015-12-17 22:20:29 +0100 |
commit | 6a4c02e107e86a0ff700b79f5a9da0f383c06430 (patch) | |
tree | a4c9d7d7e14bbf530a9c9dd441776db4248b7a78 | |
parent | 0a1a4dc033aca454c6d9a3668b5d0e5bb5ec367e (diff) | |
download | php-git-6a4c02e107e86a0ff700b79f5a9da0f383c06430.tar.gz |
Fixed bug #71154
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug71154.phpt | 19 | ||||
-rw-r--r-- | Zend/zend_hash.c | 17 |
3 files changed, 28 insertions, 10 deletions
@@ -16,6 +16,8 @@ PHP NEWS . Fixed bug #71089 (No check to duplicate zend_extension). (Remi) . Fixed bug #71086 (Invalid numeric literal parse error within highlight_string() function). (Nikita) + . Fixed bug #71154 (Incorrect HT iterator invalidation causes iterator reuse). + (Nikita) - DBA: . Fixed key leak with invalid resource. (Laruence) diff --git a/Zend/tests/bug71154.phpt b/Zend/tests/bug71154.phpt new file mode 100644 index 0000000000..6186453816 --- /dev/null +++ b/Zend/tests/bug71154.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #71154: Incorrect HT iterator invalidation causes iterator reuse +--FILE-- +<?php + +$array = [1, 2, 3]; +foreach ($array as &$ref) { + /* Free array, causing free of iterator */ + $array = []; + /* Reuse the iterator. + * However it will also be reused on next foreach iteration */ + $it = new ArrayIterator([1, 2, 3]); + $it->rewind(); +} +var_dump($it->current()); + +?> +--EXPECT-- +int(1) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index ecfee33e14..8192221c8e 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -31,6 +31,8 @@ # define HT_ASSERT(c) #endif +#define HT_POISONED_PTR ((HashTable *) (intptr_t) -1) + #if ZEND_DEBUG /* #define HASH_MASK_CONSISTENCY 0xc0 @@ -371,7 +373,8 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTab if (iter->pos == HT_INVALID_IDX) { return HT_INVALID_IDX; } else if (UNEXPECTED(iter->ht != ht)) { - if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { + if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR) + && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { iter->ht->u.v.nIteratorsCount--; } if (EXPECTED(ht->u.v.nIteratorsCount != 255)) { @@ -389,7 +392,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx) ZEND_ASSERT(idx != (uint32_t)-1); - if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { + if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR) + && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { iter->ht->u.v.nIteratorsCount--; } iter->ht = NULL; @@ -406,20 +410,13 @@ static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTabl { HashTableIterator *iter = EG(ht_iterators); HashTableIterator *end = iter + EG(ht_iterators_used); - uint32_t idx; while (iter != end) { if (iter->ht == ht) { - iter->ht = NULL; + iter->ht = HT_POISONED_PTR; } iter++; } - - idx = EG(ht_iterators_used); - while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) { - idx--; - } - EG(ht_iterators_used) = idx; } static zend_always_inline void zend_hash_iterators_remove(HashTable *ht) |