}
-void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC)
+void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, int variable TSRMLS_DC)
{
zend_op *opline;
zend_bool is_variable;
is_variable = 0;
}
+ /* save the location of the beginning of the loop (array fetching) */
+ foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
/* Preform array reset */
}
zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
}
-
- /* save the location of the beginning of the loop (array fetching) */
- opline->op2.u.opline_num = foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
+}
+
+void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znode *as_token, znode *value, znode *key, znode *cont_token TSRMLS_DC)
+{
+ zend_op *opline;
+ znode result_value, result_key, dummy;
+ zend_bool assign_by_ref=0;
+
+ cont_token->u.opline_num = get_next_op_number(CG(active_op_array));
+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FE_FETCH;
opline->result.op_type = IS_TMP_VAR;
opline->extended_value = 0;
SET_UNUSED(opline->op2);
*as_token = opline->result;
-}
-
-
-void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC)
-{
- zend_op *opline;
- znode result_value, result_key, dummy;
- zend_bool assign_by_ref=0;
if (key->op_type != IS_UNUSED) {
znode *tmp;
value = tmp;
/* Mark extended_value in case both key and value are being used */
- CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_FETCH_WITH_KEY;
+ CG(active_op_array)->opcodes[cont_token->u.opline_num].extended_value |= ZEND_FE_FETCH_WITH_KEY;
}
if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
if (value->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE) {
assign_by_ref = 1;
- if (!CG(active_op_array)->opcodes[foreach_token->u.opline_num-1].extended_value) {
+ if (!CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value) {
zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
}
/* Mark extended_value for assign-by-reference */
- CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_FETCH_BYREF;
+ CG(active_op_array)->opcodes[cont_token->u.opline_num].extended_value |= ZEND_FE_FETCH_BYREF;
}
if (key->op_type != IS_UNUSED) {
opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
result_key = opline->result;
} else {
- result_value = CG(active_op_array)->opcodes[foreach_token->u.opline_num].result;
+ result_value = CG(active_op_array)->opcodes[cont_token->u.opline_num].result;
}
if (assign_by_ref) {
if (key->op_type == IS_UNUSED) {
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
- CG(active_op_array)->opcodes[foreach_token->u.opline_num].result.op_type = IS_VAR;
- zend_do_assign_ref(NULL, value, &CG(active_op_array)->opcodes[foreach_token->u.opline_num].result TSRMLS_CC);
+ CG(active_op_array)->opcodes[cont_token->u.opline_num].result.op_type = IS_VAR;
+ zend_do_assign_ref(NULL, value, &CG(active_op_array)->opcodes[cont_token->u.opline_num].result TSRMLS_CC);
} else {
zend_do_assign_ref(NULL, value, &result_value TSRMLS_CC);
}
}
-void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC)
+void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token, znode *cont_token TSRMLS_DC)
{
zend_op *container_ptr;
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
- opline->op1.u.opline_num = foreach_token->u.opline_num;
+ opline->op1.u.opline_num = cont_token->u.opline_num;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[foreach_token->u.opline_num+1].op2.u.opline_num = cont_token->u.opline_num;
+ CG(active_op_array)->opcodes[cont_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
- do_end_loop(foreach_token->u.opline_num TSRMLS_CC);
+ do_end_loop(cont_token->u.opline_num TSRMLS_CC);
zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
generate_free_foreach_copy(container_ptr TSRMLS_CC);
void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC);
-void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC);
-void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC);
-void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC);
+void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, int variable TSRMLS_DC);
+void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znode *as_token, znode *value, znode *key, znode *cont_token TSRMLS_DC);
+void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token, znode *cont_token TSRMLS_DC);
void zend_do_declare_begin(TSRMLS_D);
void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC);
| expr ';' { zend_do_free(&$1 TSRMLS_CC); }
| T_USE use_filename ';' { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()"); zval_dtor(&$2.u.constant); }
| T_UNSET '(' unset_variables ')' ';'
- | T_FOREACH '(' variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 1 TSRMLS_CC); } foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); }
- | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 0 TSRMLS_CC); } w_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); }
+ | T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg
+ { zend_do_foreach_begin(&$1, &$2, &$3, 1 TSRMLS_CC); }
+ ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$5, &$6, &$8 TSRMLS_CC); }
+ foreach_statement { zend_do_foreach_end(&$1, &$2, &$8 TSRMLS_CC); }
+ | T_FOREACH '(' expr_without_variable T_AS w_variable foreach_optional_arg
+ { zend_do_foreach_begin(&$1, &$2, &$3, 0 TSRMLS_CC); }
+ ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$5, &$6, &$8 TSRMLS_CC); }
+ foreach_statement { zend_do_foreach_end(&$1, &$2, &$8 TSRMLS_CC); }
| T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
| ';' /* empty statement */
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
FREE_OP1_IF_VAR();
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter TSRMLS_CC);
}
- if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) {
+ if (!iter || (iter->index > 1 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) {
/* reached end of iteration */
ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
ZEND_VM_CONTINUE_JMP();
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = _get_zval_ptr_ptr_const(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- ;
- } else {
- ;
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
;
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = _get_zval_ptr_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- ;
- } else {
- ;
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
;
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
static int ZEND_JMP_NO_CTOR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter TSRMLS_CC);
}
- if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) {
+ if (!iter || (iter->index > 1 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) {
/* reached end of iteration */
ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
ZEND_VM_CONTINUE_JMP();
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), &free_op1, BP_VAR_R TSRMLS_CC);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- ;
- } else {
- ;
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
;
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
static int ZEND_JMP_NO_CTOR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
+ zend_bool is_empty = 0;
if (opline->extended_value) {
array_ptr_ptr = get_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, BP_VAR_R);
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
}
+ is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- /* probably redundant */
zend_hash_internal_pointer_reset(fe_ht);
+ if (ce) {
+ zend_object *zobj = zend_objects_get_address(array_ptr TSRMLS_CC);
+ while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
+ char *str_key;
+ uint str_key_len;
+ ulong int_key;
+ if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
+ && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_hash_move_forward(fe_ht);
+ }
+ }
+ is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-
- opline++;
- ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
- if (opline->extended_value) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- FREE_OP_IF_VAR(free_op1);
- }
- ZEND_VM_CONTINUE_JMP();
+ is_empty = 1;
}
if (opline->extended_value) {
} else {
FREE_OP_IF_VAR(free_op1);
}
- ZEND_VM_NEXT_OPCODE();
+ if (is_empty) {
+ ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_CONTINUE_JMP();
+ } else {
+ ZEND_VM_NEXT_OPCODE();
+ }
}
static int ZEND_FE_FETCH_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter TSRMLS_CC);
}
- if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) {
+ if (!iter || (iter->index > 1 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) {
/* reached end of iteration */
ZEND_VM_SET_OPCODE(EX(op_array)->opcodes+opline->op2.u.opline_num);
ZEND_VM_CONTINUE_JMP();