diff options
Diffstat (limited to 'Zend/zend_vm_def.h')
-rw-r--r-- | Zend/zend_vm_def.h | 238 |
1 files changed, 150 insertions, 88 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b4d41dfa59..45be4fc09c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -859,6 +859,8 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -885,8 +887,14 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(assign_op_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -923,7 +931,10 @@ ZEND_VM_C_LABEL(assign_op_object): } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1224,6 +1235,8 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1248,8 +1261,14 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(pre_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1263,7 +1282,10 @@ ZEND_VM_C_LABEL(pre_incdec_object): zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1291,6 +1313,8 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1315,8 +1339,14 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(post_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -1329,7 +1359,10 @@ ZEND_VM_C_LABEL(post_incdec_object): zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1988,9 +2021,11 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2009,17 +2044,17 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_r_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2027,11 +2062,18 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST } } } - } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_r_copy): @@ -2130,9 +2172,11 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2151,17 +2195,17 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_is_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2169,9 +2213,15 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_is_copy): @@ -2263,6 +2313,8 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2287,8 +2339,9 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE } ZEND_VM_C_LABEL(assign_object): + zobj = Z_OBJ_P(object); if (OP2_TYPE == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -2378,7 +2431,17 @@ ZEND_VM_C_LABEL(fast_assign_obj): ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -3431,7 +3494,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -3559,7 +3621,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -3590,13 +3651,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - ZEND_VM_C_GOTO(check_parent_and_self); + HANDLE_EXCEPTION(); } } else { -ZEND_VM_C_LABEL(check_parent_and_self): /* previous opcode is ZEND_FETCH_CLASS */ if (OP1_TYPE == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -3660,7 +3717,7 @@ ZEND_VM_C_LABEL(try_function_name): if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3718,16 +3775,8 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) SAVE_OPLINE(); function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP2(); - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -3760,14 +3809,10 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); FREE_OP2(); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -4026,9 +4071,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -4063,22 +4109,6 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(ret); - } } ZEND_VM_C_LABEL(fcall_end): @@ -4936,16 +4966,15 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM) ZEND_VM_C_GOTO(send_array); } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { OBJ_RELEASE(Z_OBJ(EX(call)->This)); } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); FREE_UNFETCHED_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -5333,6 +5362,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) USE_OPLINE zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -5366,9 +5396,10 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); FREE_OP1(); @@ -5389,7 +5420,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -6053,7 +6084,7 @@ ZEND_VM_C_LABEL(num_index_dim): if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -6070,6 +6101,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); @@ -6089,7 +6121,15 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); FREE_OP2(); @@ -6117,20 +6157,27 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -6770,6 +6817,7 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); @@ -6794,9 +6842,19 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED } } + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } ZEND_VM_C_LABEL(isset_object_finish): FREE_OP2(); @@ -6877,9 +6935,10 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -6908,7 +6967,8 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -7923,8 +7983,8 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } FREE_OP1(); @@ -8459,18 +8519,20 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED) count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; |