diff options
-rw-r--r-- | Zend/zend_execute.c | 10 | ||||
-rw-r--r-- | Zend/zend_operators.c | 4 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 593 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 4804 | ||||
-rw-r--r-- | Zend/zend_vm_gen.php | 25 |
5 files changed, 3158 insertions, 2278 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 340cd9b481..40868f0dc8 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -57,6 +57,7 @@ typedef int (ZEND_FASTCALL *incdec_t)(zval *); #define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type) #define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type) #define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type) +#define get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) _get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) #define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) /* Prototypes */ @@ -516,6 +517,15 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_execute_dat return get_zval_ptr(op_type, op, execute_data, should_free, type); } +static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type) +{ + if (op_type == IS_UNUSED) { + *should_free = NULL; + return &EX(This); + } + return get_zval_ptr_undef(op_type, op, execute_data, should_free, type); +} + static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_execute_data *execute_data, zend_free_op *should_free, int type) { if (op_type == IS_UNUSED) { diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index dc02c03899..aa20bcaf59 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1391,7 +1391,7 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o } if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { - ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_or_function); + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function); op1_lval = _zval_get_long_func(op1); } else { op1_lval = Z_LVAL_P(op1); @@ -1458,7 +1458,7 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o } if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { - ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_or_function); + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function); op1_lval = _zval_get_long_func(op1); } else { op1_lval = Z_LVAL_P(op1); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0f9cdffc87..c3011eb9bc 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -251,8 +251,8 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) zval *op1, *op2; SAVE_OPLINE(); - op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); - op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); + op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); + op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); do { if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -290,6 +290,12 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } FREE_OP1(); @@ -350,18 +356,18 @@ ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV) do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -393,10 +399,10 @@ ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV) } while (0); SAVE_OPLINE(); - if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -419,18 +425,18 @@ ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV) do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -462,10 +468,10 @@ ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV) } while (0); SAVE_OPLINE(); - if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -1434,7 +1440,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY) zval *z; SAVE_OPLINE(); - z = GET_OP1_ZVAL_PTR(BP_VAR_R); + z = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (Z_TYPE_P(z) == IS_STRING) { zend_string *str = Z_STR_P(z); @@ -1447,6 +1453,8 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY) if (str->len != 0) { zend_write(str->val, str->len); + } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(z, BP_VAR_R); } zend_string_release(str); } @@ -1466,7 +1474,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V HashTable *target_symbol_table; SAVE_OPLINE(); - varname = GET_OP1_ZVAL_PTR(BP_VAR_R); + varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_CONST) { name = Z_STR_P(varname); @@ -1474,6 +1482,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V name = Z_STR_P(varname); zend_string_addref(name); } else { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -2077,7 +2088,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST) zval *container; SAVE_OPLINE(); - container = GET_OP1_ZVAL_PTR(BP_VAR_R); + container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); ZEND_VM_C_LABEL(try_fetch_list): if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -2106,6 +2117,9 @@ ZEND_VM_C_LABEL(try_fetch_list): container = Z_REFVAL_P(container); ZEND_VM_C_GOTO(try_fetch_list); } else { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(container, BP_VAR_R); + } ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -2229,7 +2243,7 @@ ZEND_VM_C_LABEL(assign_dim_convert_to_array): ZEND_VM_C_GOTO(try_assign_dim_array); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { ZEND_VM_C_GOTO(assign_dim_clean); } ZEND_VM_C_GOTO(assign_dim_convert_to_array); @@ -2683,17 +2697,27 @@ ZEND_VM_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) zend_string *op1_str, *op2_str, *str; SAVE_OPLINE(); - op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); - op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); + op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (OP1_TYPE != IS_CONST) { @@ -2746,11 +2770,22 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV) var = GET_OP2_ZVAL_PTR(BP_VAR_R); rope[0] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = GET_OP2_ZVAL_PTR(BP_VAR_R); - rope[0] = zval_get_string(var); - FREE_OP2(); - CHECK_EXCEPTION(); + var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (OP2_TYPE == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[0] = _zval_get_string_func(var); + FREE_OP2(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -2768,11 +2803,22 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV) var = GET_OP2_ZVAL_PTR(BP_VAR_R); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = GET_OP2_ZVAL_PTR(BP_VAR_R); - rope[opline->extended_value] = zval_get_string(var); - FREE_OP2(); - CHECK_EXCEPTION(); + var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (OP2_TYPE == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); + FREE_OP2(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -2792,11 +2838,22 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV) var = GET_OP2_ZVAL_PTR(BP_VAR_R); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = GET_OP2_ZVAL_PTR(BP_VAR_R); - rope[opline->extended_value] = zval_get_string(var); - FREE_OP2(); - CHECK_EXCEPTION(); + var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (OP2_TYPE == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); + FREE_OP2(); + CHECK_EXCEPTION(); + } } for (i = 0; i <= opline->extended_value; i++) { len += rope[i]->len; @@ -2828,7 +2885,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV) ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_op2; - zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval *class_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); ZEND_VM_C_LABEL(try_class_name): if (OP2_TYPE == IS_CONST) { @@ -2846,6 +2903,9 @@ ZEND_VM_C_LABEL(try_class_name): class_name = Z_REFVAL_P(class_name); ZEND_VM_C_GOTO(try_class_name); } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(class_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2872,7 +2932,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR SAVE_OPLINE(); - function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -2883,6 +2943,9 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR break; } } + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2893,7 +2956,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR } while (0); } - object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); + object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -2910,6 +2973,9 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR break; } } + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3015,9 +3081,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE } else if (OP2_TYPE != IS_UNUSED) { zend_free_op free_op2; - function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3145,7 +3214,7 @@ ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV) uint32_t call_info = ZEND_CALL_NESTED_FUNCTION; SAVE_OPLINE(); - function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); ZEND_VM_C_LABEL(try_function_name): if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { @@ -3325,6 +3394,9 @@ ZEND_VM_C_LABEL(try_function_name): function_name = Z_REFVAL_P(function_name); ZEND_VM_C_GOTO(try_function_name); } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4053,7 +4125,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) zend_free_op free_op1; SAVE_OPLINE(); - value = GET_OP1_ZVAL_PTR(BP_VAR_R); + value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); do { if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { @@ -4063,6 +4135,9 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) break; } } + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4348,71 +4423,67 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY) int arg_num; SAVE_OPLINE(); - args = GET_OP1_ZVAL_PTR(BP_VAR_R); + args = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; ZEND_VM_C_LABEL(send_again): - switch (Z_TYPE_P(args)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(args); - zval *arg, *top; - zend_string *name; - - zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); - - if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { - uint32_t i; - int separate = 0; - - /* check if any of arguments are going to be passed by reference */ - for (i = 0; i < zend_hash_num_elements(ht); i++) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) { - separate = 1; - break; - } - } - if (separate) { - zval_copy_ctor(args); - ht = Z_ARRVAL_P(args); + if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(args); + zval *arg, *top; + zend_string *name; + + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); + + if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { + uint32_t i; + int separate = 0; + + /* check if any of arguments are going to be passed by reference */ + for (i = 0; i < zend_hash_num_elements(ht); i++) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) { + separate = 1; + break; } } + if (separate) { + zval_copy_ctor(args); + ht = Z_ARRVAL_P(args); + } + } - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { - if (name) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys"); - FREE_OP1(); - HANDLE_EXCEPTION(); - } + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (name) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys"); + FREE_OP1(); + HANDLE_EXCEPTION(); + } - top = ZEND_CALL_ARG(EX(call), arg_num); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - if (!Z_IMMUTABLE_P(args)) { - ZVAL_MAKE_REF(arg); - Z_ADDREF_P(arg); - ZVAL_REF(top, Z_REF_P(arg)); - } else { - ZVAL_DUP(top, arg); - } - } else if (Z_ISREF_P(arg)) { - ZVAL_COPY(top, Z_REFVAL_P(arg)); + top = ZEND_CALL_ARG(EX(call), arg_num); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + if (!Z_IMMUTABLE_P(args)) { + ZVAL_MAKE_REF(arg); + Z_ADDREF_P(arg); + ZVAL_REF(top, Z_REF_P(arg)); } else { - ZVAL_COPY(top, arg); + ZVAL_DUP(top, arg); } + } else if (Z_ISREF_P(arg)) { + ZVAL_COPY(top, Z_REFVAL_P(arg)); + } else { + ZVAL_COPY(top, arg); + } - ZEND_CALL_NUM_ARGS(EX(call))++; - arg_num++; - } ZEND_HASH_FOREACH_END(); + ZEND_CALL_NUM_ARGS(EX(call))++; + arg_num++; + } ZEND_HASH_FOREACH_END(); - break; - } - case IS_OBJECT: { - zend_class_entry *ce = Z_OBJCE_P(args); - zend_object_iterator *iter; + } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(args); + zend_object_iterator *iter; - if (!ce || !ce->get_iterator) { - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); - break; - } + if (!ce || !ce->get_iterator) { + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + } else { iter = ce->get_iterator(ce, args, 0); if (UNEXPECTED(!iter)) { @@ -4490,14 +4561,15 @@ ZEND_VM_C_LABEL(send_again): ZEND_VM_C_LABEL(unpack_iter_dtor): zend_iterator_dtor(iter); - break; } - case IS_REFERENCE: - args = Z_REFVAL_P(args); - ZEND_VM_C_GOTO(send_again); - break; - default: - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + } else if (EXPECTED(Z_ISREF_P(args))) { + args = Z_REFVAL_P(args); + ZEND_VM_C_GOTO(send_again); + } else { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(args, BP_VAR_R); + } + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); } FREE_OP1(); @@ -4825,18 +4897,18 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV) do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -4867,10 +4939,10 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV) } while (0); SAVE_OPLINE(); - if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -4946,7 +5018,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); + obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(obj) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -4961,7 +5033,10 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY) if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; } - } + } + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(obj, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -5132,7 +5207,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE SAVE_OPLINE(); if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -5145,11 +5220,11 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE } else { expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (OP1_TYPE == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (OP1_TYPE == IS_CV) { @@ -5175,48 +5250,46 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE if (OP2_TYPE != IS_UNUSED) { zend_free_op free_op2; - zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval *offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); zend_string *str; zend_ulong hval; ZEND_VM_C_LABEL(add_again): - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - ZEND_VM_C_GOTO(num_index); - case IS_LONG: - hval = Z_LVAL_P(offset); -ZEND_VM_C_LABEL(num_index): - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - ZEND_VM_C_GOTO(num_index); - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (OP2_TYPE != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + ZEND_VM_C_GOTO(num_index); } + } ZEND_VM_C_LABEL(str_index): - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - ZEND_VM_C_GOTO(str_index); - case IS_FALSE: - hval = 0; - ZEND_VM_C_GOTO(num_index); - case IS_TRUE: - hval = 1; - ZEND_VM_C_GOTO(num_index); - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - ZEND_VM_C_GOTO(add_again); - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +ZEND_VM_C_LABEL(num_index): + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + ZEND_VM_C_GOTO(add_again); + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index); + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + ZEND_VM_C_GOTO(num_index); + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + ZEND_VM_C_GOTO(num_index); + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + ZEND_VM_C_GOTO(num_index); + } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index); + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } FREE_OP2(); } else { @@ -5372,10 +5445,13 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY) zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R); + inc_filename = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) { + inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R); + } ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -5518,10 +5594,13 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR) ZEND_VM_NEXT_OPCODE(); } - varname = GET_OP1_ZVAL_PTR(BP_VAR_R); + varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); ZVAL_UNDEF(&tmp); if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -5574,6 +5653,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV) zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); @@ -5587,69 +5667,79 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV) FREE_UNFETCHED_OP2(); HANDLE_EXCEPTION(); } - offset = GET_OP2_ZVAL_PTR(BP_VAR_R); + offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); -ZEND_VM_C_LABEL(unset_dim_again): - if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +ZEND_VM_C_LABEL(unset_dim_array): + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); ZEND_VM_C_LABEL(offset_again): - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -ZEND_VM_C_LABEL(num_index_dim): - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { ZEND_VM_C_GOTO(num_index_dim); } } +ZEND_VM_C_LABEL(str_index_dim): if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +ZEND_VM_C_LABEL(num_index_dim): + zend_hash_index_del(ht, hval); + } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + ZEND_VM_C_GOTO(offset_again); + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + ZEND_VM_C_GOTO(num_index_dim); + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index_dim); + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; ZEND_VM_C_GOTO(num_index_dim); - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; ZEND_VM_C_GOTO(num_index_dim); - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); ZEND_VM_C_GOTO(num_index_dim); - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - ZEND_VM_C_GOTO(offset_again); - break; - default: + } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index_dim); + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + ZEND_VM_C_GOTO(unset_dim_array); + } } - } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - ZEND_VM_C_GOTO(unset_dim_again); - } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); + FREE_OP2(); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -6476,7 +6566,7 @@ ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|T HANDLE_EXCEPTION(); } - offset = GET_OP2_ZVAL_PTR(BP_VAR_R); + offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -6499,30 +6589,31 @@ ZEND_VM_C_LABEL(str_index_prop): hval = Z_LVAL_P(offset); ZEND_VM_C_LABEL(num_index_prop): value = zend_hash_index_find(ht, hval); + } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + ZEND_VM_C_GOTO(isset_again); + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + ZEND_VM_C_GOTO(num_index_prop); + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index_prop); + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + ZEND_VM_C_GOTO(num_index_prop); + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + ZEND_VM_C_GOTO(num_index_prop); + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + ZEND_VM_C_GOTO(num_index_prop); + } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + ZEND_VM_C_GOTO(str_index_prop); } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - ZEND_VM_C_GOTO(num_index_prop); - case IS_NULL: - str = STR_EMPTY_ALLOC(); - ZEND_VM_C_GOTO(str_index_prop); - case IS_FALSE: - hval = 0; - ZEND_VM_C_GOTO(num_index_prop); - case IS_TRUE: - hval = 1; - ZEND_VM_C_GOTO(num_index_prop); - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - ZEND_VM_C_GOTO(num_index_prop); - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - ZEND_VM_C_GOTO(isset_again); - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - ZEND_VM_C_GOTO(isset_not_found); - } + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + ZEND_VM_C_GOTO(isset_not_found); } if (opline->extended_value & ZEND_ISSET) { @@ -6539,6 +6630,11 @@ ZEND_VM_C_LABEL(num_index_prop): ZEND_VM_C_GOTO(isset_dim_obj_array); } } + + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (OP1_TYPE == IS_UNUSED || (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -6962,7 +7058,7 @@ ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, CONST|VAR) zend_bool result; SAVE_OPLINE(); - expr = GET_OP1_ZVAL_PTR(BP_VAR_R); + expr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); ZEND_VM_C_LABEL(try_instanceof): if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -6989,6 +7085,9 @@ ZEND_VM_C_LABEL(try_instanceof): expr = Z_REFVAL_P(expr); ZEND_VM_C_GOTO(try_instanceof); } else { + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(expr, BP_VAR_R); + } result = 0; } FREE_OP1(); @@ -7404,7 +7503,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); FREE_UNFETCHED_OP2(); FREE_UNFETCHED_OP1(); @@ -7421,7 +7520,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE if (OP1_TYPE != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { @@ -7431,11 +7530,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE value = GET_OP1_ZVAL_PTR(BP_VAR_R); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (OP1_TYPE != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (OP1_TYPE != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); @@ -7465,11 +7563,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* Consts, temporary variables and references need copying */ if (OP1_TYPE == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (OP1_TYPE == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); FREE_OP1_IF_VAR(); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -7490,11 +7591,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* Consts, temporary variables and references need copying */ if (OP2_TYPE == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (OP2_TYPE == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((OP2_TYPE == IS_VAR || OP2_TYPE == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); FREE_OP2_IF_VAR(); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -7803,13 +7907,16 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) zend_free_op free_op1; SAVE_OPLINE(); - value = GET_OP1_ZVAL_PTR(BP_VAR_R); + value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); ZEND_VM_C_LABEL(try_strlen): if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); } else { zend_bool strict; + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); ZEND_VM_C_GOTO(try_strlen); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index aa68c9644b..206cd86b07 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -926,71 +926,67 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_ int arg_num; SAVE_OPLINE(); - args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R); + args = get_zval_ptr_undef(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; send_again: - switch (Z_TYPE_P(args)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(args); - zval *arg, *top; - zend_string *name; - - zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); - - if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { - uint32_t i; - int separate = 0; - - /* check if any of arguments are going to be passed by reference */ - for (i = 0; i < zend_hash_num_elements(ht); i++) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) { - separate = 1; - break; - } - } - if (separate) { - zval_copy_ctor(args); - ht = Z_ARRVAL_P(args); + if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(args); + zval *arg, *top; + zend_string *name; + + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); + + if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { + uint32_t i; + int separate = 0; + + /* check if any of arguments are going to be passed by reference */ + for (i = 0; i < zend_hash_num_elements(ht); i++) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) { + separate = 1; + break; } } + if (separate) { + zval_copy_ctor(args); + ht = Z_ARRVAL_P(args); + } + } - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { - if (name) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys"); - FREE_OP(free_op1); - HANDLE_EXCEPTION(); - } + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (name) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys"); + FREE_OP(free_op1); + HANDLE_EXCEPTION(); + } - top = ZEND_CALL_ARG(EX(call), arg_num); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - if (!Z_IMMUTABLE_P(args)) { - ZVAL_MAKE_REF(arg); - Z_ADDREF_P(arg); - ZVAL_REF(top, Z_REF_P(arg)); - } else { - ZVAL_DUP(top, arg); - } - } else if (Z_ISREF_P(arg)) { - ZVAL_COPY(top, Z_REFVAL_P(arg)); + top = ZEND_CALL_ARG(EX(call), arg_num); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + if (!Z_IMMUTABLE_P(args)) { + ZVAL_MAKE_REF(arg); + Z_ADDREF_P(arg); + ZVAL_REF(top, Z_REF_P(arg)); } else { - ZVAL_COPY(top, arg); + ZVAL_DUP(top, arg); } + } else if (Z_ISREF_P(arg)) { + ZVAL_COPY(top, Z_REFVAL_P(arg)); + } else { + ZVAL_COPY(top, arg); + } - ZEND_CALL_NUM_ARGS(EX(call))++; - arg_num++; - } ZEND_HASH_FOREACH_END(); + ZEND_CALL_NUM_ARGS(EX(call))++; + arg_num++; + } ZEND_HASH_FOREACH_END(); - break; - } - case IS_OBJECT: { - zend_class_entry *ce = Z_OBJCE_P(args); - zend_object_iterator *iter; + } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(args); + zend_object_iterator *iter; - if (!ce || !ce->get_iterator) { - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); - break; - } + if (!ce || !ce->get_iterator) { + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + } else { iter = ce->get_iterator(ce, args, 0); if (UNEXPECTED(!iter)) { @@ -1068,14 +1064,15 @@ send_again: unpack_iter_dtor: zend_iterator_dtor(iter); - break; } - case IS_REFERENCE: - args = Z_REFVAL_P(args); - goto send_again; - break; - default: - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + } else if (EXPECTED(Z_ISREF_P(args))) { + args = Z_REFVAL_P(args); + goto send_again; + } else { + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(args, BP_VAR_R); + } + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); } FREE_OP(free_op1); @@ -2000,6 +1997,9 @@ try_class_name: class_name = Z_REFVAL_P(class_name); goto try_class_name; } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(class_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2232,6 +2232,9 @@ try_function_name: function_name = Z_REFVAL_P(function_name); goto try_function_name; } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2432,6 +2435,9 @@ try_class_name: class_name = Z_REFVAL_P(class_name); goto try_class_name; } else { + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(class_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2457,7 +2463,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } else { - zval *class_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *class_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); try_class_name: if (IS_CV == IS_CONST) { @@ -2475,6 +2481,9 @@ try_class_name: class_name = Z_REFVAL_P(class_name); goto try_class_name; } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(class_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2499,7 +2508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HAND uint32_t call_info = ZEND_CALL_NESTED_FUNCTION; SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); try_function_name: if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { @@ -2679,6 +2688,9 @@ try_function_name: function_name = Z_REFVAL_P(function_name); goto try_function_name; } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2727,6 +2739,9 @@ try_class_name: class_name = Z_REFVAL_P(class_name); goto try_class_name; } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(class_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2932,6 +2947,9 @@ try_function_name: function_name = Z_REFVAL_P(function_name); goto try_function_name; } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3006,6 +3024,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_O if (str->len != 0) { zend_write(str->val, str->len); + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(z, BP_VAR_R); } zend_string_release(str); } @@ -3386,6 +3406,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_ break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3558,7 +3581,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_ if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; } - } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(obj, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3729,6 +3755,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) { + inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R); + } ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -4351,6 +4380,9 @@ try_strlen: } else { zend_bool strict; + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -4700,6 +4732,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLE ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -4760,18 +4798,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HAND do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -4803,10 +4841,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HAND } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -4829,18 +4867,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_ do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -4872,10 +4910,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_ } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -5083,6 +5121,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -5547,6 +5588,9 @@ try_fetch_list: container = Z_REFVAL_P(container); goto try_fetch_list; } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(container, BP_VAR_R); + } ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -5562,16 +5606,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_H SAVE_OPLINE(); op1 = EX_CONSTANT(opline->op1); - op2 = EX_CONSTANT(opline->op2); if (IS_CONST == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = EX_CONSTANT(opline->op2); if (IS_CONST == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CONST != IS_CONST) { @@ -5636,6 +5690,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -5663,6 +5720,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -5769,6 +5829,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = EX_CONSTANT(opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -5922,18 +5985,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER( do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -5964,10 +6027,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER( } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -6095,7 +6158,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C SAVE_OPLINE(); if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -6108,11 +6171,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } else { expr_ptr = EX_CONSTANT(opline->op1); if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CONST == IS_CV) { @@ -6143,43 +6206,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -6254,6 +6315,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HAN ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -6445,30 +6509,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -6485,6 +6550,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CONST == IS_UNUSED || (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -6627,7 +6697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -6644,7 +6714,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER if (IS_CONST != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { @@ -6654,11 +6724,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -6687,11 +6756,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -6712,11 +6784,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -6818,7 +6893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -6835,7 +6910,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z if (IS_CONST != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { @@ -6845,11 +6920,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -6878,11 +6952,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -6903,11 +6980,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -7005,6 +7085,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -7205,6 +7288,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDL ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -7362,7 +7448,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -7379,7 +7465,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z if (IS_CONST != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { @@ -7389,11 +7475,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -7422,11 +7507,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -7447,11 +7535,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -7509,6 +7600,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -7762,6 +7856,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -7909,7 +8006,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U SAVE_OPLINE(); if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -7922,11 +8019,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U } else { expr_ptr = EX_CONSTANT(opline->op1); if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CONST == IS_CV) { @@ -7957,43 +8054,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -8068,6 +8163,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -8248,7 +8346,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -8265,7 +8363,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE if (IS_CONST != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { @@ -8275,11 +8373,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -8308,11 +8405,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -8333,11 +8433,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -8604,7 +8707,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z SAVE_OPLINE(); op1 = EX_CONSTANT(opline->op1); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); do { if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -8642,6 +8745,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -8702,18 +8811,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -8745,10 +8854,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -8771,18 +8880,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HAN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -8814,10 +8923,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HAN } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -9278,16 +9387,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND SAVE_OPLINE(); op1 = EX_CONSTANT(opline->op1); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_CONST == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CONST != IS_CONST) { @@ -9341,7 +9460,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -9352,6 +9471,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9379,6 +9501,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9482,9 +9607,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } else if (IS_CV != IS_UNUSED) { - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9689,18 +9817,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -9731,10 +9859,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEN } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -9753,7 +9881,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C SAVE_OPLINE(); if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -9766,11 +9894,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } else { expr_ptr = EX_CONSTANT(opline->op1); if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CONST == IS_CV) { @@ -9796,48 +9924,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); zend_string *str; zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -9896,7 +10022,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -9919,30 +10045,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -9959,6 +10086,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CONST == IS_UNUSED || (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -10064,7 +10196,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -10081,7 +10213,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE if (IS_CONST != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { @@ -10091,11 +10223,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -10124,11 +10255,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -10149,11 +10283,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -10473,6 +10610,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -10493,18 +10636,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HAN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -10536,10 +10679,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HAN } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -10562,18 +10705,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -10605,10 +10748,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -11071,16 +11214,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ SAVE_OPLINE(); op1 = EX_CONSTANT(opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CONST == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CONST != IS_CONST) { @@ -11145,6 +11298,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -11172,6 +11328,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -11279,6 +11438,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -11433,18 +11595,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -11475,10 +11637,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER } while (0); SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -11497,7 +11659,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T SAVE_OPLINE(); if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -11510,11 +11672,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T } else { expr_ptr = EX_CONSTANT(opline->op1); if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CONST == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CONST == IS_CV) { @@ -11545,43 +11707,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } zval_ptr_dtor_nogc(free_op2); } else { @@ -11663,30 +11823,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -11703,6 +11864,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CONST == IS_UNUSED || (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -11990,6 +12156,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OP break; } } + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -12889,11 +13058,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLE var = EX_CONSTANT(opline->op2); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = EX_CONSTANT(opline->op2); - rope[opline->extended_value] = zval_get_string(var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -12913,11 +13093,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE var = EX_CONSTANT(opline->op2); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = EX_CONSTANT(opline->op2); - rope[opline->extended_value] = zval_get_string(var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } for (i = 0; i <= opline->extended_value; i++) { len += rope[i]->len; @@ -12943,7 +13134,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON SAVE_OPLINE(); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -12956,11 +13147,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_TMP_VAR == IS_CV) { @@ -12991,43 +13182,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -13075,7 +13264,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13092,7 +13281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -13102,11 +13291,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_TMP_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -13135,11 +13323,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -13160,11 +13351,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -13251,7 +13445,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13268,7 +13462,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -13278,11 +13472,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_TMP_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -13311,11 +13504,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -13336,11 +13532,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -13427,7 +13626,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13444,7 +13643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -13454,11 +13653,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_TMP_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -13487,11 +13685,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -13512,11 +13713,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -13660,7 +13864,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU SAVE_OPLINE(); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -13673,11 +13877,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_TMP_VAR == IS_CV) { @@ -13708,43 +13912,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -13792,7 +13994,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13809,7 +14011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -13819,11 +14021,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_TMP_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -13852,11 +14053,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -13877,11 +14081,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -14133,11 +14340,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(Z var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - rope[opline->extended_value] = zval_get_string(var); + var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -14157,11 +14375,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - rope[opline->extended_value] = zval_get_string(var); + var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } for (i = 0; i <= opline->extended_value; i++) { len += rope[i]->len; @@ -14187,7 +14416,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ SAVE_OPLINE(); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -14200,11 +14429,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_TMP_VAR == IS_CV) { @@ -14230,48 +14459,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); zend_string *str; zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -14319,7 +14546,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -14336,7 +14563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { @@ -14346,11 +14573,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_TMP_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -14379,11 +14605,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -14404,11 +14633,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -14621,11 +14853,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - rope[opline->extended_value] = zval_get_string(var); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -14645,11 +14888,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - rope[opline->extended_value] = zval_get_string(var); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[opline->extended_value] = _zval_get_string_func(var); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + } } for (i = 0; i <= opline->extended_value; i++) { len += rope[i]->len; @@ -14675,7 +14929,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP SAVE_OPLINE(); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -14688,11 +14942,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } else { expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_TMP_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_TMP_VAR == IS_CV) { @@ -14723,43 +14977,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } zval_ptr_dtor_nogc(free_op2); } else { @@ -15148,6 +15400,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OP break; } } + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -17469,7 +17724,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -17565,6 +17820,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = EX_CONSTANT(opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -17768,7 +18026,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -17781,11 +18039,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_VAR == IS_CV) { @@ -17816,43 +18074,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -17900,6 +18156,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -17915,67 +18172,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL } offset = EX_CONSTANT(opline->op2); -unset_dim_again: - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -18033,7 +18299,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18050,7 +18316,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -18060,11 +18326,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -18094,11 +18359,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(free_op1); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -18119,11 +18387,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -18244,7 +18515,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18261,7 +18532,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -18271,11 +18542,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -18305,11 +18575,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(free_op1); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -18330,11 +18603,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -18512,7 +18788,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18529,7 +18805,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -18539,11 +18815,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -18573,11 +18848,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(free_op1); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -18598,11 +18876,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -19110,7 +19391,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -19177,6 +19458,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -19324,7 +19608,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -19337,11 +19621,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_VAR == IS_CV) { @@ -19372,43 +19656,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -19473,7 +19755,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -19490,7 +19772,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -19500,11 +19782,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -19534,11 +19815,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(free_op1); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -19559,11 +19843,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -20640,7 +20927,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -20794,9 +21081,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } else if (IS_CV != IS_UNUSED) { - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -20891,7 +21181,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -20904,11 +21194,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_VAR == IS_CV) { @@ -20934,48 +21224,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); zend_string *str; zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -21023,6 +21311,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER( zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -21036,69 +21325,78 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER( HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); -unset_dim_again: - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -21156,7 +21454,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -21173,7 +21471,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { @@ -21183,11 +21481,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_VAR != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -21217,11 +21514,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(free_op1); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -21242,11 +21542,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -22293,7 +22596,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -22360,6 +22663,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -22454,7 +22760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -22467,11 +22773,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP } else { expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_VAR == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_VAR == IS_CV) { @@ -22502,43 +22808,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } zval_ptr_dtor_nogc(free_op2); } else { @@ -22586,6 +22890,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -22601,67 +22906,77 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -unset_dim_again: - if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); + zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); @@ -22743,7 +23058,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; } - } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(obj, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -23676,11 +23994,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HA var = EX_CONSTANT(opline->op2); rope[0] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = EX_CONSTANT(opline->op2); - rope[0] = zval_get_string(var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[0] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -23710,6 +24039,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -23737,6 +24069,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C break; } } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -23946,6 +24281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HA zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); @@ -23961,67 +24297,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HA } offset = EX_CONSTANT(opline->op2); -unset_dim_again: - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); CHECK_EXCEPTION(); @@ -24113,30 +24458,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -24153,6 +24499,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_UNUSED == IS_UNUSED || (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -24258,7 +24609,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -24275,7 +24626,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE if (IS_UNUSED != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -24285,11 +24636,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -24318,11 +24668,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -24343,11 +24696,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -24394,7 +24750,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -24411,7 +24767,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( if (IS_UNUSED != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -24421,11 +24777,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -24454,11 +24809,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -24479,11 +24837,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -24530,7 +24891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -24547,7 +24908,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( if (IS_UNUSED != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -24557,11 +24918,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -24590,11 +24950,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -24615,11 +24978,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -25044,7 +25410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -25061,7 +25427,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL if (IS_UNUSED != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -25071,11 +25437,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -25104,11 +25469,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -25129,11 +25497,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -26021,11 +26392,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDL var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); rope[0] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - rope[0] = zval_get_string(var); + var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[0] = _zval_get_string_func(var); - CHECK_EXCEPTION(); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -26044,7 +26426,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -26055,6 +26437,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -26082,6 +26467,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C break; } } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -26182,6 +26570,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDL zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); @@ -26195,69 +26584,78 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDL HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); -unset_dim_again: - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); CHECK_EXCEPTION(); @@ -26326,7 +26724,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNU HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -26349,30 +26747,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -26389,6 +26788,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_UNUSED == IS_UNUSED || (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -26494,7 +26898,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -26511,7 +26915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z if (IS_UNUSED != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { @@ -26521,11 +26925,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_UNUSED != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = NULL; @@ -26554,11 +26957,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -26579,11 +26985,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -27476,11 +27885,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); rope[0] = zend_string_copy(Z_STR_P(var)); } else { - SAVE_OPLINE(); var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - rope[0] = zval_get_string(var); - zval_ptr_dtor_nogc(free_op2); - CHECK_EXCEPTION(); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(var, BP_VAR_R); + } + rope[0] = _zval_get_string_func(var); + zval_ptr_dtor_nogc(free_op2); + CHECK_EXCEPTION(); + } } ZEND_VM_NEXT_OPCODE(); } @@ -27510,6 +27930,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -27537,6 +27960,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T break; } } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -27638,6 +28064,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_H zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); @@ -27653,67 +28080,77 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_H } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -unset_dim_again: - if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); @@ -27806,30 +28243,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -27846,6 +28284,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_UNUSED == IS_UNUSED || (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -28160,7 +28603,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + z = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (Z_TYPE_P(z) == IS_STRING) { zend_string *str = Z_STR_P(z); @@ -28173,6 +28616,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO if (str->len != 0) { zend_write(str->val, str->len); + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(z, BP_VAR_R); } zend_string_release(str); } @@ -28543,7 +28988,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + value = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); do { if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { @@ -28553,6 +28998,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -28821,7 +29269,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + obj = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(obj) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -28836,7 +29284,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; } - } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(obj, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -29003,10 +29454,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + inc_filename = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) { + inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R); + } ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -29622,13 +30076,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + value = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); } else { zend_bool strict; + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -29919,7 +30376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); op2 = EX_CONSTANT(opline->op2); do { @@ -29958,6 +30415,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -30018,18 +30481,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -30061,10 +30524,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -30087,18 +30550,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -30130,10 +30593,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -30889,7 +31352,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { name = Z_STR_P(varname); @@ -30897,6 +31360,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -31497,7 +31963,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDL zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); try_fetch_list: if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -31526,6 +31992,9 @@ try_fetch_list: container = Z_REFVAL_P(container); goto try_fetch_list; } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(container, BP_VAR_R); + } ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -31649,7 +32118,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -31709,17 +32178,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND zend_string *op1_str, *op2_str, *str; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - op2 = EX_CONSTANT(opline->op2); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = EX_CONSTANT(opline->op2); if (IS_CONST == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CV != IS_CONST) { @@ -31784,6 +32263,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -31794,7 +32276,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST } while (0); } - object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -31811,6 +32293,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -31884,18 +32369,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -31926,10 +32411,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEN } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -31948,7 +32433,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -31961,11 +32446,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CV == IS_CV) { @@ -31996,43 +32481,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -32103,10 +32586,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLE ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -32159,6 +32645,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); @@ -32174,67 +32661,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE } offset = EX_CONSTANT(opline->op2); -unset_dim_again: - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); CHECK_EXCEPTION(); @@ -32431,30 +32927,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -32471,6 +32968,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CV == IS_UNUSED || (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -32577,7 +33079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDL zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + expr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -32604,6 +33106,9 @@ try_instanceof: expr = Z_REFVAL_P(expr); goto try_instanceof; } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(expr, BP_VAR_R); + } result = 0; } @@ -32620,7 +33125,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -32637,7 +33142,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE if (IS_CV != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -32647,11 +33152,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); @@ -32680,11 +33184,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -32705,11 +33212,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Consts, temporary variables and references need copying */ if (IS_CONST == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -32926,7 +33436,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -32943,7 +33453,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND if (IS_CV != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -32953,11 +33463,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); @@ -32986,11 +33495,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -33011,11 +33523,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -33105,7 +33620,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { name = Z_STR_P(varname); @@ -33113,6 +33628,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -33399,10 +33917,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER( ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -33561,7 +34082,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + expr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -33588,6 +34109,9 @@ try_instanceof: expr = Z_REFVAL_P(expr); goto try_instanceof; } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(expr, BP_VAR_R); + } result = 0; } @@ -33604,7 +34128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -33621,7 +34145,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND if (IS_CV != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -33631,11 +34155,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); @@ -33664,11 +34187,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -33689,11 +34215,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); zval_ptr_dtor_nogc(free_op2); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -34037,7 +34566,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { name = Z_STR_P(varname); @@ -34045,6 +34574,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -34385,7 +34917,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -34469,7 +35001,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -34482,11 +35014,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CV == IS_CV) { @@ -34517,43 +35049,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_UNUSED != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -34624,10 +35154,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -34785,7 +35318,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -34802,7 +35335,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z if (IS_CV != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -34812,11 +35345,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); @@ -34845,11 +35377,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -34870,11 +35405,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Consts, temporary variables and references need copying */ if (IS_UNUSED == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -35140,8 +35678,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); do { if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -35179,6 +35717,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -35239,18 +35783,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -35282,10 +35826,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -35308,18 +35852,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -35351,10 +35895,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -36644,7 +37188,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -36764,17 +37308,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER zend_string *op1_str, *op2_str, *str; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CV != IS_CONST) { @@ -36828,7 +37382,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -36839,6 +37393,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -36849,7 +37406,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } while (0); } - object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -36866,6 +37423,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -36939,18 +37499,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_O do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -36981,10 +37541,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_O } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -37003,7 +37563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -37016,11 +37576,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CV == IS_CV) { @@ -37046,48 +37606,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); zend_string *str; zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } } else { @@ -37135,6 +37693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); @@ -37148,69 +37707,78 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); -unset_dim_again: - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); CHECK_EXCEPTION(); @@ -37279,7 +37847,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_ HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -37302,30 +37870,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -37342,6 +37911,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CV == IS_UNUSED || (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -37447,7 +38021,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ zend_generator *generator = zend_get_running_generator(execute_data); SAVE_OPLINE(); - if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -37464,7 +38038,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ if (IS_CV != IS_UNUSED) { - if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { @@ -37474,11 +38048,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); - - /* Temporary variables don't need ctor copying */ - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(&generator->value); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); @@ -37507,11 +38080,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->value, value); + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { + zval_copy_ctor_func(&generator->value); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) { - ZVAL_DUP(&generator->value, Z_REFVAL_P(value)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { ZVAL_COPY_VALUE(&generator->value, value); @@ -37532,11 +38108,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Consts, temporary variables and references need copying */ if (IS_CV == IS_CONST) { - ZVAL_DUP(&generator->key, key); + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) { + zval_copy_ctor_func(&generator->key); + } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) { - ZVAL_DUP(&generator->key, Z_REFVAL_P(key)); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); } else { ZVAL_COPY_VALUE(&generator->key, key); @@ -37822,7 +38401,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); do { @@ -37861,6 +38440,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } @@ -37881,18 +38466,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -37924,10 +38509,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -37950,18 +38535,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -37993,10 +38578,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -39292,7 +39877,7 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (UNEXPECTED(object_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { goto assign_dim_clean; } goto assign_dim_convert_to_array; @@ -39323,17 +39908,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN zend_string *op1_str, *op2_str, *str; SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if (IS_CV != IS_CONST) { @@ -39398,6 +39993,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -39408,7 +40006,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } while (0); } - object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context"); @@ -39425,6 +40023,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -39499,18 +40100,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -39541,10 +40142,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZE } while (0); SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -39563,7 +40164,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && - (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); @@ -39576,11 +40177,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&new_expr, expr_ptr); - expr_ptr = &new_expr; + /* pass */ } else if (IS_CV == IS_CONST) { - if (!Z_IMMUTABLE_P(expr_ptr)) { - ZVAL_DUP(&new_expr, expr_ptr); + if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + zval_copy_ctor_func(&new_expr); expr_ptr = &new_expr; } } else if (IS_CV == IS_CV) { @@ -39611,43 +40212,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV zend_ulong hval; add_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index: - zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); - break; - case IS_STRING: - str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index; - } + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; } + } str_index: - zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); - break; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index; - case IS_FALSE: - hval = 0; - goto num_index; - case IS_TRUE: - hval = 1; - goto num_index; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto add_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - zval_ptr_dtor(expr_ptr); - /* do nothing */ - break; + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(expr_ptr); } zval_ptr_dtor_nogc(free_op2); } else { @@ -39695,6 +40294,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL zval *container; zval *offset; zend_ulong hval; + zend_string *key; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); @@ -39710,67 +40310,77 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); -unset_dim_again: - if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; + do { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); offset_again: - SEPARATE_ARRAY(container); - ht = Z_ARRVAL_P(container); - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); -num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { goto num_index_dim; } } +str_index_dim: if (ht == &EG(symbol_table)) { - zend_delete_global_variable(Z_STR_P(offset)); + zend_delete_global_variable(key); } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_del(ht, key); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; goto num_index_dim; - case IS_TRUE: + } else if (Z_TYPE_P(offset) == IS_TRUE) { hval = 1; goto num_index_dim; - case IS_RESOURCE: + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { hval = Z_RES_HANDLE_P(offset); goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + key = STR_EMPTY_ALLOC(); + goto str_index_dim; + } else { zend_error(E_WARNING, "Illegal offset type in unset"); - break; + } + break; + } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); - } else { - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); } - } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - goto unset_dim_again; - } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); - } + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } + } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + } + } while (0); + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); @@ -39863,30 +40473,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -39903,6 +40514,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if (IS_CV == IS_UNUSED || (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -40080,6 +40696,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_ if (str->len != 0) { zend_write(str->val, str->len); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(z, BP_VAR_R); } zend_string_release(str); } @@ -40363,7 +40981,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; } - } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(obj, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -40431,6 +41052,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) { + inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R); + } ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -40588,6 +41212,9 @@ try_strlen: } else { zend_bool strict; + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = GET_OP1_UNDEF_CV(value, BP_VAR_R); + } if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -40880,6 +41507,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } zval_ptr_dtor_nogc(free_op1); @@ -40900,18 +41533,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -40943,10 +41576,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -40969,18 +41602,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -41012,10 +41645,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -41223,6 +41856,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -41529,6 +42165,9 @@ try_fetch_list: container = Z_REFVAL_P(container); goto try_fetch_list; } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(container, BP_VAR_R); + } ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -41544,16 +42183,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - op2 = EX_CONSTANT(opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = EX_CONSTANT(opline->op2); if (IS_CONST == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -41618,6 +42267,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C break; } } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -41645,6 +42297,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -41719,18 +42374,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -41761,10 +42416,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -41809,6 +42464,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HA ZVAL_UNDEF(&tmp); if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -42001,30 +42659,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -42041,6 +42700,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -42174,6 +42838,9 @@ try_instanceof: expr = Z_REFVAL_P(expr); goto try_instanceof; } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(expr, BP_VAR_R); + } result = 0; } zval_ptr_dtor_nogc(free_op1); @@ -42216,6 +42883,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -42417,6 +43087,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HAND ZVAL_UNDEF(&tmp); if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -42603,6 +43276,9 @@ try_instanceof: expr = Z_REFVAL_P(expr); goto try_instanceof; } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(expr, BP_VAR_R); + } result = 0; } zval_ptr_dtor_nogc(free_op1); @@ -42630,6 +43306,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ name = Z_STR_P(varname); zend_string_addref(name); } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } name = zval_get_string(varname); } @@ -42831,6 +43510,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H ZVAL_UNDEF(&tmp); if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -43209,7 +43891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); do { if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -43247,6 +43929,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } zval_ptr_dtor_nogc(free_op1); @@ -43267,18 +43955,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -43310,10 +43998,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLE } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -43336,18 +44024,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HA do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -43379,10 +44067,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HA } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -43684,16 +44372,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -43747,7 +44445,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -43758,6 +44456,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C break; } } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -43785,6 +44486,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -43859,18 +44563,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -43901,10 +44605,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -43933,7 +44637,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -43956,30 +44660,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -43996,6 +44701,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { @@ -44374,6 +45084,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND ZVAL_NEW_STR(EX_VAR(opline->result.var), str); } } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } concat_function(EX_VAR(opline->result.var), op1, op2); } zval_ptr_dtor_nogc(free_op1); @@ -44394,18 +45110,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -44437,10 +45153,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -44463,18 +45179,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2))); } else { break; @@ -44506,10 +45222,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -44812,16 +45528,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR SAVE_OPLINE(); op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); } else { - op1_str = zval_get_string(op1); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(op1, BP_VAR_R); + } + op1_str = _zval_get_string_func(op1); } + op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); } else { - op2_str = zval_get_string(op2); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(op2, BP_VAR_R); + } + op2_str = _zval_get_string_func(op2); } do { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -44886,6 +45612,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -44913,6 +45642,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T break; } } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(object, BP_VAR_R); + } if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -44988,18 +45720,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE do { int result; - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2)); } else { break; } - } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { - if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2))); } else { break; @@ -45030,10 +45762,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE } while (0); SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R); } - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R); } result = EX_VAR(opline->result.var); @@ -45085,30 +45817,31 @@ str_index_prop: hval = Z_LVAL_P(offset); num_index_prop: value = zend_hash_index_find(ht, hval); - } else { - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - goto num_index_prop; - case IS_NULL: - str = STR_EMPTY_ALLOC(); - goto str_index_prop; - case IS_FALSE: - hval = 0; - goto num_index_prop; - case IS_TRUE: - hval = 1; - goto num_index_prop; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_prop; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto isset_again; - default: - zend_error(E_WARNING, "Illegal offset type in isset or empty"); - goto isset_not_found; - } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_prop; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + hval = Z_RES_HANDLE_P(offset); + goto num_index_prop; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + GET_OP2_UNDEF_CV(offset, BP_VAR_R); + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + } else { + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + goto isset_not_found; } if (opline->extended_value & ZEND_ISSET) { @@ -45125,6 +45858,11 @@ num_index_prop: goto isset_dim_obj_array; } } + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R); + } + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) { if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 7d49bea509..0b8caadc74 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -259,6 +259,26 @@ $op2_get_obj_zval_ptr = array( "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)", ); +$op1_get_obj_zval_ptr_undef = array( + "ANY" => "get_obj_zval_ptr_undef(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)", + "VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)", + "CONST" => "EX_CONSTANT(opline->op1)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data)", + "CV" => "_get_zval_ptr_cv_undef(execute_data, opline->op1.var)", + "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)", +); + +$op2_get_obj_zval_ptr_undef = array( + "ANY" => "get_obj_zval_ptr_undef(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)", + "VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)", + "CONST" => "EX_CONSTANT(opline->op2)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data)", + "CV" => "_get_zval_ptr_cv_undef(execute_data, opline->op2.var)", + "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)", +); + $op1_get_obj_zval_ptr_deref = array( "ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)", "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)", @@ -449,6 +469,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $op1_get_zval_ptr_ptr, $op2_get_zval_ptr_ptr, $op1_get_zval_ptr_ptr_undef, $op2_get_zval_ptr_ptr_undef, $op1_get_obj_zval_ptr, $op2_get_obj_zval_ptr, + $op1_get_obj_zval_ptr_undef, $op2_get_obj_zval_ptr_undef, $op1_get_obj_zval_ptr_deref, $op2_get_obj_zval_ptr_deref, $op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr, $op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef, @@ -475,6 +496,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { "/GET_OP2_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/", "/GET_OP1_OBJ_ZVAL_PTR\(([^)]*)\)/", "/GET_OP2_OBJ_ZVAL_PTR\(([^)]*)\)/", + "/GET_OP1_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/", + "/GET_OP2_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/", "/GET_OP1_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/", "/GET_OP2_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/", "/GET_OP1_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/", @@ -517,6 +540,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $op2_get_zval_ptr_ptr_undef[$op2], $op1_get_obj_zval_ptr[$op1], $op2_get_obj_zval_ptr[$op2], + $op1_get_obj_zval_ptr_undef[$op1], + $op2_get_obj_zval_ptr_undef[$op2], $op1_get_obj_zval_ptr_deref[$op1], $op2_get_obj_zval_ptr_deref[$op2], $op1_get_obj_zval_ptr_ptr[$op1], |