diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index 00bc30160ab7b..b158c3f92730d 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -130,6 +130,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) memset(&fake_execute_data, 0, sizeof(zend_execute_data)); fake_execute_data.func = (zend_function*)op_array; + fake_execute_data.opline = op_array->opcodes; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { diff --git a/Zend/zend.c b/Zend/zend.c index 46a0e1b4c0ea3..31899f14af400 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1601,6 +1601,28 @@ ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message) { zend_error_zstr_at(type, filename, lineno, message); } +/* Assert that global state was properly setup before entering a function that + * may trigger an error. */ +ZEND_API void zend_may_error(void) +{ + if (!zend_is_executing()) { + return; + } + + zend_long lineno_override = EG(lineno_override); + if (lineno_override != -1) { + return; + } + + zend_execute_data *ex = EG(current_execute_data); + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + + /* zend_error() will dereference ex->opline */ + ZEND_ASSERT(!ex || ex->opline); +} + ZEND_API void zend_begin_record_errors(void) { ZEND_ASSERT(!EG(record_errors) && "Error recording already enabled"); diff --git a/Zend/zend.h b/Zend/zend.h index 3eaf62ace1157..81b6d792f9694 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -351,6 +351,7 @@ ZEND_API ZEND_COLD void zend_error_at(int type, zend_string *filename, uint32_t ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn(int type, zend_string *filename, uint32_t lineno, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 4, 5); ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message); ZEND_API ZEND_COLD void zend_error_zstr_at(int type, zend_string *filename, uint32_t lineno, zend_string *message); +ZEND_API void zend_may_error(void); ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 5f11f49b07157..213bbc89c27c5 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2586,6 +2586,9 @@ ZEND_API void ZEND_FASTCALL _efree_huge(void *ptr, size_t size) ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { +#if ZEND_DEBUG + zend_may_error(); +#endif #if ZEND_MM_CUSTOM if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { return _malloc_custom(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -2607,6 +2610,9 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { +#if ZEND_DEBUG + zend_may_error(); +#endif #if ZEND_MM_CUSTOM if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { return _realloc_custom(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -2617,6 +2623,9 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { +#if ZEND_DEBUG + zend_may_error(); +#endif #if ZEND_MM_CUSTOM if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { return _realloc_custom(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8f993190ab178..f8b4f99de2807 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -638,6 +638,10 @@ ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */ ex = ex->prev_execute_data; } if (ex) { + if (!ex->opline) { + /* Missing SAVE_OPLINE()? Falling back to first line of function */ + return ex->func->op_array.opcodes[0].lineno; + } if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION && ex->opline->lineno == 0 && EG(opline_before_exception)) { return EG(opline_before_exception)->lineno; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b1c629d8bbb23..fcc08648784ea 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -406,6 +406,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -417,6 +418,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -3161,6 +3163,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -3169,6 +3172,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -3323,6 +3327,7 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM) uint32_t i; size_t len = 0; char *target; + SAVE_OPLINE(); rope = (zend_string**)EX_VAR(opline->op1.var); if (OP2_TYPE == IS_CONST) { @@ -3340,7 +3345,6 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM) rope[opline->extended_value] = Z_STR_P(var); } } else { - SAVE_OPLINE(); if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } @@ -4915,6 +4919,7 @@ ZEND_VM_C_LABEL(send_var_by_ref): if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -6049,7 +6054,7 @@ ZEND_VM_C_LABEL(add_unpack_again): if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(op1); zval *val; - + if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { zend_hash_extend(result_ht, zend_hash_num_elements(result_ht) + zend_hash_num_elements(ht), 1); ZEND_HASH_FILL_PACKED(result_ht) { @@ -6174,6 +6179,7 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSE zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (OP1_TYPE != IS_UNUSED) { @@ -7478,6 +7484,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) } } if (!EG(error_reporting_ini_entry)->modified) { + SAVE_OPLINE(); if (!EG(modified_ini_directives)) { ALLOC_HASHTABLE(EG(modified_ini_directives)); zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); @@ -7616,7 +7623,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|VAR|CV, JMP_ADDR) uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { ZVAL_NULL(result); - if (OP1_TYPE == IS_CV + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 ) { @@ -8075,6 +8082,8 @@ ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM) called_scope = Z_CE(EX(This)); object = NULL; } + + SAVE_OPLINE(); zend_create_closure(EX_VAR(opline->result.var), func, EX(func)->op_array.scope, called_scope, object); @@ -8424,6 +8433,7 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT) value = zend_hash_find_known_hash(&EG(symbol_table), varname); if (UNEXPECTED(value == NULL)) { + SAVE_OPLINE(); value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval)); idx = (char*)value - (char*)EG(symbol_table).arData; /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ @@ -8443,6 +8453,7 @@ ZEND_VM_C_LABEL(check_indirect): } if (UNEXPECTED(!Z_ISREF_P(value))) { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(value, 2); ref = Z_REF_P(value); } else { @@ -8849,6 +8860,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) HashTable *ht; zval *value; zval *variable_ptr; + SAVE_OPLINE(); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -8861,7 +8873,6 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))); - SAVE_OPLINE(); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { @@ -8946,6 +8957,7 @@ ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED) if (OP1_TYPE == IS_CV) { if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); ZVAL_NEW_EMPTY_REF(op1); Z_SET_REFCOUNT_P(op1, 2); ZVAL_NULL(Z_REFVAL_P(op1)); @@ -8954,6 +8966,7 @@ ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED) if (Z_ISREF_P(op1)) { Z_ADDREF_P(op1); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); @@ -8961,6 +8974,7 @@ ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED) } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } else { GC_ADDREF(Z_REF_P(op1)); @@ -9316,6 +9330,7 @@ ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED) if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + SAVE_OPLINE(); ht = zend_new_array(result_size); ZVAL_ARR(EX_VAR(opline->result.var), ht); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b86c90be2b3b2..c325f42f91249 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2986,6 +2986,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN } } if (!EG(error_reporting_ini_entry)->modified) { + SAVE_OPLINE(); if (!EG(modified_ini_directives)) { ALLOC_HASHTABLE(EG(modified_ini_directives)); zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); @@ -5447,6 +5448,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C called_scope = Z_CE(EX(This)); object = NULL; } + + SAVE_OPLINE(); zend_create_closure(EX_VAR(opline->result.var), func, EX(func)->op_array.scope, called_scope, object); @@ -6635,6 +6638,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -6643,6 +6647,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -7318,6 +7323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { @@ -8555,6 +8561,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -8566,6 +8573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -8979,6 +8987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -8987,6 +8996,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -9514,6 +9524,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_H zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { @@ -10437,6 +10448,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_H zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { @@ -10803,6 +10815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + SAVE_OPLINE(); ht = zend_new_array(result_size); ZVAL_ARR(EX_VAR(opline->result.var), ht); @@ -10920,6 +10933,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -10931,6 +10945,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -11344,6 +11359,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -11352,6 +11368,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -11878,6 +11895,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDL zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { @@ -14950,6 +14968,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -14961,6 +14980,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -15688,6 +15708,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -15696,6 +15717,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -16386,6 +16408,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -16397,6 +16420,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -17124,6 +17148,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -17132,6 +17157,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -18073,6 +18099,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -18084,6 +18111,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -18449,6 +18477,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -18457,6 +18486,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -19661,6 +19691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE uint32_t i; size_t len = 0; char *target; + SAVE_OPLINE(); rope = (zend_string**)EX_VAR(opline->op1.var); if (IS_CONST == IS_CONST) { @@ -19678,7 +19709,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE rope[opline->extended_value] = Z_STR_P(var); } } else { - SAVE_OPLINE(); if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } @@ -19847,6 +19877,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HAND zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { @@ -20138,6 +20169,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL uint32_t i; size_t len = 0; char *target; + SAVE_OPLINE(); rope = (zend_string**)EX_VAR(opline->op1.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -20155,7 +20187,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL 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)) { ZVAL_UNDEFINED_OP2(); } @@ -20287,6 +20318,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { @@ -20748,6 +20780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HAN zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { @@ -20999,6 +21032,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z uint32_t i; size_t len = 0; char *target; + SAVE_OPLINE(); rope = (zend_string**)EX_VAR(opline->op1.var); if (IS_CV == IS_CONST) { @@ -21016,7 +21050,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z rope[opline->extended_value] = Z_STR_P(var); } } else { - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } @@ -21148,6 +21181,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { @@ -24611,6 +24645,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HAN if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -24884,6 +24919,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { @@ -27176,6 +27212,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { @@ -28873,6 +28910,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HA if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -28939,6 +28977,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_V if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -29197,6 +29236,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HAN zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { @@ -29359,6 +29399,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL if (IS_VAR == IS_CV) { if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); ZVAL_NEW_EMPTY_REF(op1); Z_SET_REFCOUNT_P(op1, 2); ZVAL_NULL(Z_REFVAL_P(op1)); @@ -29367,6 +29408,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL if (Z_ISREF_P(op1)) { Z_ADDREF_P(op1); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); @@ -29374,6 +29416,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } else { GC_ADDREF(Z_REF_P(op1)); @@ -31452,6 +31495,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { @@ -33628,6 +33672,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_H zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_UNUSED != IS_UNUSED) { @@ -35367,6 +35412,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_ zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_UNUSED != IS_UNUSED) { @@ -36004,6 +36050,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_ zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_UNUSED != IS_UNUSED) { @@ -36264,6 +36311,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + SAVE_OPLINE(); ht = zend_new_array(result_size); ZVAL_ARR(EX_VAR(opline->result.var), ht); @@ -37839,6 +37887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HAND zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_UNUSED != IS_UNUSED) { @@ -39817,6 +39866,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -39828,6 +39878,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -42312,6 +42363,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -42320,6 +42372,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -42656,6 +42709,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HAND if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -42793,6 +42847,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { @@ -43304,6 +43359,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C value = zend_hash_find_known_hash(&EG(symbol_table), varname); if (UNEXPECTED(value == NULL)) { + SAVE_OPLINE(); value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval)); idx = (char*)value - (char*)EG(symbol_table).arData; /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ @@ -43323,6 +43379,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C } if (UNEXPECTED(!Z_ISREF_P(value))) { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(value, 2); ref = Z_REF_P(value); } else { @@ -43628,6 +43685,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -43639,6 +43697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -46052,6 +46111,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -46060,6 +46120,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -46392,6 +46453,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HAND zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { @@ -48095,6 +48157,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HAN if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -48160,6 +48223,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_C if (Z_ISREF_P(varptr)) { Z_ADDREF_P(varptr); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(varptr, 2); } ZVAL_REF(arg, Z_REF_P(varptr)); @@ -48297,6 +48361,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HAND zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { @@ -48636,6 +48701,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN HashTable *ht; zval *value; zval *variable_ptr; + SAVE_OPLINE(); variable_ptr = EX_VAR(opline->op1.var); @@ -48648,7 +48714,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))); - SAVE_OPLINE(); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { @@ -48698,6 +48763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE if (IS_CV == IS_CV) { if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); ZVAL_NEW_EMPTY_REF(op1); Z_SET_REFCOUNT_P(op1, 2); ZVAL_NULL(Z_REFVAL_P(op1)); @@ -48706,6 +48772,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE if (Z_ISREF_P(op1)) { Z_ADDREF_P(op1); } else { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); @@ -48713,6 +48780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { op1 = Z_INDIRECT_P(op1); if (EXPECTED(!Z_ISREF_P(op1))) { + SAVE_OPLINE(); ZVAL_MAKE_REF_EX(op1, 2); } else { GC_ADDREF(Z_REF_P(op1)); @@ -48921,6 +48989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -48932,6 +49001,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -51444,6 +51514,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { size_t len = ZSTR_LEN(op1_str); + SAVE_OPLINE(); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -51452,6 +51523,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER zend_string_release_ex(op2_str, 0); } } else { + SAVE_OPLINE(); str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -51784,6 +51856,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER( zval *array; uint32_t size; USE_OPLINE + SAVE_OPLINE(); array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index f71468549e6af..e6e2609b83a41 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4424,6 +4424,7 @@ static int accel_preload(const char *config, bool in_child) memset(&fake_execute_data, 0, sizeof(fake_execute_data)); fake_execute_data.func = (zend_function*)&script->script.main_op_array; + fake_execute_data.opline = script->script.main_op_array.opcodes; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { script->compiler_halt_offset = Z_LVAL_P(offset); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index de2fa51526d0c..6f3abdefe17b6 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -2279,6 +2279,7 @@ static int zend_jit_hybrid_hot_code_stub(dasm_State **Dst) } |->hybrid_hot_code: + | SAVE_IP | mov word [r2], ZEND_JIT_COUNTER_INIT | mov FCARG1a, FP | GET_IP FCARG2a @@ -2368,6 +2369,7 @@ static int zend_jit_hybrid_hot_trace_stub(dasm_State **Dst) } |->hybrid_hot_trace: + | SAVE_IP | mov word [r2], ZEND_JIT_COUNTER_INIT | mov FCARG1a, FP | GET_IP FCARG2a @@ -5518,6 +5520,7 @@ static int zend_jit_concat_helper(dasm_State **Dst, | LOAD_ZVAL_ADDR FCARG1a, res_addr } | LOAD_ZVAL_ADDR FCARG2a, op2_addr + | SET_EX_OPLINE opline, r0 | EXT_CALL zend_jit_fast_assign_concat_helper, r0 /* concatenation with itself may reduce refcount */ op2_info |= MAY_BE_RC1; @@ -5532,6 +5535,7 @@ static int zend_jit_concat_helper(dasm_State **Dst, | sub r4, 12 | PUSH_ZVAL_ADDR op2_addr, r0 |.endif + | SET_EX_OPLINE opline, r0 if (op1_type == IS_CV || op1_type == IS_CONST) { | EXT_CALL zend_jit_fast_concat_helper, r0 } else { @@ -10559,6 +10563,7 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend } | mov aword T1, r0 // save } + | SET_EX_OPLINE opline, r0 | EMALLOC sizeof(zend_reference), op_array, opline | mov dword [r0], 2 | mov dword [r0 + offsetof(zend_reference, gc.u.type_info)], GC_REFERENCE @@ -12589,6 +12594,7 @@ static int zend_jit_bind_global(dasm_State **Dst, const zend_op *opline, uint32_ if (opline->extended_value) { | add FCARG2a, opline->extended_value } + | SET_EX_OPLINE opline, r0 | EXT_CALL zend_jit_fetch_global_helper, r0 | jmp <1 |.code @@ -15677,6 +15683,7 @@ static int zend_jit_rope(dasm_State **Dst, const zend_op *opline, uint32_t op2_i | lea FCARG1a, [FP + opline->op1.var] | mov FCARG2d, opline->extended_value + | SET_EX_OPLINE opline, r0 | EXT_CALL zend_jit_rope_end, r0 | SET_ZVAL_PTR res_addr, r0 | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index dcff7a7883289..63945683dbf36 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -382,6 +382,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc memset(&fake_execute_data, 0, sizeof(fake_execute_data)); fake_execute_data.func = (zend_function*)op_array; + fake_execute_data.opline = op_array->opcodes; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);