From 5112a4ae2435913d41be52ceb0a541d56803d7df Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Fri, 7 Nov 2003 10:47:47 +0000 Subject: [PATCH] Update Iterators: Call next at the correct point in time. --- Zend/zend_execute.c | 25 ++++++++++++++++++------- Zend/zend_iterators.h | 3 ++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b7758c5252..a3e557f218 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3584,6 +3584,7 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; if (iter) { + iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); } @@ -3612,6 +3613,7 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) ulong int_key; HashTable *fe_ht; zend_object_iterator *iter = NULL; + int key_type; PZVAL_LOCK(array); @@ -3629,16 +3631,29 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; return 0; /* CHECK_ME */ } + key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL); break; case ZEND_ITER_OBJECT: /* !iter happens from exception */ + if (iter && iter->index++) { + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + iter->funcs->move_forward(iter TSRMLS_CC); + } if (!iter || iter->funcs->has_more(iter TSRMLS_CC) == FAILURE) { /* reached end of iteration */ EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; return 0; /* CHECK_ME */ } iter->funcs->get_current_data(iter, &value TSRMLS_CC); + if (iter->funcs->get_current_key) { + key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + } else { + key_type = HASH_KEY_IS_LONG; + int_key = iter->index; + } + break; } @@ -3653,10 +3668,8 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) ALLOC_ZVAL(key); INIT_PZVAL(key); - - switch (iter ? - iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC) : - zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL)) { + + switch (key_type) { case HASH_KEY_IS_STRING: key->value.str.val = str_key; key->value.str.len = str_key_len-1; @@ -3670,9 +3683,7 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) } zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); - if (iter) { - iter->funcs->move_forward(iter TSRMLS_CC); - } else { + if (!iter) { zend_hash_move_forward(fe_ht); } diff --git a/Zend/zend_iterators.h b/Zend/zend_iterators.h index 4a05fdd942..f23a023dda 100755 --- a/Zend/zend_iterators.h +++ b/Zend/zend_iterators.h @@ -38,7 +38,7 @@ typedef struct _zend_object_iterator_funcs { /* fetch the item data for the current element */ void (*get_current_data)(zend_object_iterator *iter, zval ***data TSRMLS_DC); - /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) */ + /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */ int (*get_current_key)(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); /* step forwards to next element */ @@ -51,6 +51,7 @@ typedef struct _zend_object_iterator_funcs { struct _zend_object_iterator { void *data; zend_object_iterator_funcs *funcs; + ulong index; /* private to fe_reset/fe_fetch opcodes */ }; typedef zval *(*zend_object_new_iterator_t)(zend_class_entry *ce, zval *object TSRMLS_DC); -- 2.40.0