From 226d9f33935348ba0126fde6f83ee091c7b727e1 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Wed, 11 Nov 2020 14:25:39 -0800 Subject: [PATCH 1/9] Provide unused retvals to observers --- Zend/zend_vm_def.h | 4 +-- Zend/zend_vm_execute.h | 6 ++-- ext/zend_test/tests/observer_retval_01.phpt | 22 ++++++++++++++ ext/zend_test/tests/observer_retval_02.phpt | 32 +++++++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 ext/zend_test/tests/observer_retval_01.phpt create mode 100644 ext/zend_test/tests/observer_retval_02.phpt diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c8e7774efcbe3..b3d54dc4a95cd 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4304,7 +4304,7 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } } ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, return_value); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -4365,7 +4365,7 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, FREE_OP1_VAR_PTR(); } while (0); - ZEND_OBSERVER_FCALL_END(execute_data, EX(return_value)); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6fca6f4d138c9..35fa1751f77a3 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4157,7 +4157,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } } SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, return_value); + zend_observer_fcall_end(execute_data, retval_ptr); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4277,7 +4277,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } while (0); - zend_observer_fcall_end(execute_data, EX(return_value)); + zend_observer_fcall_end(execute_data, retval_ptr); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -54830,7 +54830,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, return_value); + zend_observer_fcall_end(execute_data, retval_ptr); goto zend_leave_helper_SPEC_LABEL; } diff --git a/ext/zend_test/tests/observer_retval_01.phpt b/ext/zend_test/tests/observer_retval_01.phpt new file mode 100644 index 0000000000000..7885606e8cfdc --- /dev/null +++ b/ext/zend_test/tests/observer_retval_01.phpt @@ -0,0 +1,22 @@ +--TEST-- +Observer: Unused retvals are still observable +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_02.phpt b/ext/zend_test/tests/observer_retval_02.phpt new file mode 100644 index 0000000000000..6b2e3548a2aac --- /dev/null +++ b/ext/zend_test/tests/observer_retval_02.phpt @@ -0,0 +1,32 @@ +--TEST-- +Observer: Unused retvals from generators are still observable +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- +current(); +$gen->next(); +$gen->current(); + +echo 'Done' . PHP_EOL; +?> +--EXPECTF-- + + + + + + + +Done + From 69061b924a74f9b6ce295245721b3c3190afd5d2 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Thu, 12 Nov 2020 10:37:41 -0800 Subject: [PATCH 2/9] Fix IS_CV + refcounted return case Also add loads more tests for various VM var types --- Zend/zend_vm_def.h | 14 +- Zend/zend_vm_execute.h | 140 +++++++++++++++--- ext/zend_test/test.c | 9 +- ext/zend_test/tests/observer_retval_01.phpt | 13 +- ext/zend_test/tests/observer_retval_03.phpt | 32 ++++ ext/zend_test/tests/observer_retval_04.phpt | 40 +++++ ext/zend_test/tests/observer_retval_05.phpt | 33 +++++ ext/zend_test/tests/observer_retval_06.phpt | 30 ++++ ext/zend_test/tests/observer_retval_07.phpt | 39 +++++ .../tests/observer_retval_by_ref_01.phpt | 30 ++++ .../tests/observer_retval_by_ref_02.phpt | 34 +++++ .../tests/observer_retval_by_ref_03.phpt | 42 ++++++ 12 files changed, 430 insertions(+), 26 deletions(-) create mode 100644 ext/zend_test/tests/observer_retval_03.phpt create mode 100644 ext/zend_test/tests/observer_retval_04.phpt create mode 100644 ext/zend_test/tests/observer_retval_05.phpt create mode 100644 ext/zend_test/tests/observer_retval_06.phpt create mode 100644 ext/zend_test/tests/observer_retval_07.phpt create mode 100644 ext/zend_test/tests/observer_retval_by_ref_01.phpt create mode 100644 ext/zend_test/tests/observer_retval_by_ref_02.phpt create mode 100644 ext/zend_test/tests/observer_retval_by_ref_03.phpt diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b3d54dc4a95cd..cae91a423e9c5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4248,6 +4248,8 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) if (return_value) { ZVAL_NULL(return_value); } + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else if (!return_value) { if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -4255,6 +4257,8 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else { if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -4263,6 +4267,8 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) Z_ADDREF_P(return_value); } } + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else if (OP1_TYPE == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4274,6 +4280,8 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -4286,6 +4294,8 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } while (0); } else /* if (OP1_TYPE == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4301,10 +4311,10 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } } - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 35fa1751f77a3..779493e8a0a20 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4027,6 +4027,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -4034,6 +4036,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -4042,6 +4046,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ Z_ADDREF_P(return_value); } } + + } else if (IS_CONST == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4053,6 +4059,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -4065,6 +4073,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_CONST == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4080,10 +4090,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4101,6 +4111,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER if (return_value) { ZVAL_NULL(return_value); } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -4108,6 +4120,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else { if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -4116,6 +4130,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER Z_ADDREF_P(return_value); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else if (opline->op1_type == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4127,6 +4143,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -4139,6 +4157,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } } ZVAL_COPY_VALUE(return_value, retval_ptr); + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } while (0); } else /* if (opline->op1_type == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4154,10 +4174,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -18534,6 +18554,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -18541,6 +18563,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -18549,6 +18573,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA Z_ADDREF_P(return_value); } } + + } else if (IS_TMP_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -18560,6 +18586,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -18572,6 +18600,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -18587,10 +18617,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -21100,6 +21130,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -21107,6 +21139,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -21115,6 +21149,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA Z_ADDREF_P(return_value); } } + + } else if (IS_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -21126,6 +21162,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -21138,6 +21176,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -21153,10 +21193,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -37632,6 +37672,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -37639,6 +37681,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -37647,6 +37691,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN Z_ADDREF_P(return_value); } } + + } else if (IS_CV == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -37658,6 +37704,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -37670,6 +37718,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_CV == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -37685,10 +37735,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -54699,6 +54749,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -54706,6 +54758,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -54714,6 +54768,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } + + } else if (IS_CONST == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -54725,6 +54781,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -54737,6 +54795,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_CONST == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -54752,10 +54812,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } goto zend_leave_helper_SPEC_LABEL; } @@ -54774,6 +54834,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (return_value) { ZVAL_NULL(return_value); } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -54781,6 +54843,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else { if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -54789,6 +54853,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } else if (opline->op1_type == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -54800,6 +54866,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -54812,6 +54880,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } while (0); } else /* if (opline->op1_type == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -54827,10 +54897,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); goto zend_leave_helper_SPEC_LABEL; } @@ -56309,6 +56379,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -56316,6 +56388,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -56324,6 +56398,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } + + } else if (IS_TMP_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -56335,6 +56411,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -56347,6 +56425,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -56362,10 +56442,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } goto zend_leave_helper_SPEC_LABEL; } @@ -56608,6 +56688,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -56615,6 +56697,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -56623,6 +56707,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } + + } else if (IS_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -56634,6 +56720,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -56646,6 +56734,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -56661,10 +56751,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } goto zend_leave_helper_SPEC_LABEL; } @@ -57723,6 +57813,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (return_value) { ZVAL_NULL(return_value); } + + } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { @@ -57730,6 +57822,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } + + } else { if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -57738,6 +57832,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } + + } else if (IS_CV == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -57749,6 +57845,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); + + break; } else { Z_ADDREF_P(retval_ptr); @@ -57761,6 +57859,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); + + } while (0); } else /* if (IS_CV == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -57776,10 +57876,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - } - } + } + } goto zend_leave_helper_SPEC_LABEL; } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index ef6d45b84986b..b6f848c5b7c5a 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -480,7 +480,14 @@ static void get_retval_info(zval *retval, smart_str *buf) if (retval == NULL) { smart_str_appendl(buf, "NULL", 4); } else if (ZT_G(observer_show_return_value)) { - php_var_export_ex(retval, 2 * ZT_G(observer_nesting_depth) + 3, buf); + if (Z_TYPE_P(retval) == IS_OBJECT) { + smart_str_appendl(buf, "object(", 7); + smart_str_append(buf, Z_OBJCE_P(retval)->name); + smart_str_appendl(buf, ")#", 2); + smart_str_append_long(buf, Z_OBJ_HANDLE_P(retval)); + } else { + php_var_export_ex(retval, 2 * ZT_G(observer_nesting_depth) + 3, buf); + } } else if (ZT_G(observer_show_return_type)) { smart_str_appends(buf, zend_zval_type_name(retval)); } diff --git a/ext/zend_test/tests/observer_retval_01.phpt b/ext/zend_test/tests/observer_retval_01.phpt index 7885606e8cfdc..d58cac807d268 100644 --- a/ext/zend_test/tests/observer_retval_01.phpt +++ b/ext/zend_test/tests/observer_retval_01.phpt @@ -1,5 +1,5 @@ --TEST-- -Observer: Unused retvals are still observable +Observer: Retvals are observable that are: IS_CONST --SKIPIF-- --INI-- @@ -8,8 +8,13 @@ zend_test.observer.observe_all=1 zend_test.observer.show_return_value=1 --FILE-- --EXPECTF-- @@ -18,5 +23,7 @@ echo 'Done' . PHP_EOL; + + Done diff --git a/ext/zend_test/tests/observer_retval_03.phpt b/ext/zend_test/tests/observer_retval_03.phpt new file mode 100644 index 0000000000000..a21ed97c25363 --- /dev/null +++ b/ext/zend_test/tests/observer_retval_03.phpt @@ -0,0 +1,32 @@ +--TEST-- +Observer: Retvals are observable that are: refcounted, IS_CV +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_04.phpt b/ext/zend_test/tests/observer_retval_04.phpt new file mode 100644 index 0000000000000..2e69857fb426b --- /dev/null +++ b/ext/zend_test/tests/observer_retval_04.phpt @@ -0,0 +1,40 @@ +--TEST-- +Observer: Retvals are observable that are: refcounted, IS_VAR +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_05.phpt b/ext/zend_test/tests/observer_retval_05.phpt new file mode 100644 index 0000000000000..45fe981f29abe --- /dev/null +++ b/ext/zend_test/tests/observer_retval_05.phpt @@ -0,0 +1,33 @@ +--TEST-- +Observer: Retvals are observable that are: IS_CV, IS_UNDEF +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + +Warning: Undefined variable $i_do_not_exist in %s on line %d + + + +Warning: Undefined variable $i_do_not_exist in %s on line %d + +Done + diff --git a/ext/zend_test/tests/observer_retval_06.phpt b/ext/zend_test/tests/observer_retval_06.phpt new file mode 100644 index 0000000000000..f5d2988725f60 --- /dev/null +++ b/ext/zend_test/tests/observer_retval_06.phpt @@ -0,0 +1,30 @@ +--TEST-- +Observer: Retvals are observable that are: IS_CV +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_07.phpt b/ext/zend_test/tests/observer_retval_07.phpt new file mode 100644 index 0000000000000..abd518b0e423c --- /dev/null +++ b/ext/zend_test/tests/observer_retval_07.phpt @@ -0,0 +1,39 @@ +--TEST-- +Observer: Retvals are observable that are: IS_REFERENCE, IS_VAR +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_by_ref_01.phpt b/ext/zend_test/tests/observer_retval_by_ref_01.phpt new file mode 100644 index 0000000000000..4e96ab010bd78 --- /dev/null +++ b/ext/zend_test/tests/observer_retval_by_ref_01.phpt @@ -0,0 +1,30 @@ +--TEST-- +Observer: Retvals by reference are observable that are: IS_CV +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + +Done + diff --git a/ext/zend_test/tests/observer_retval_by_ref_02.phpt b/ext/zend_test/tests/observer_retval_by_ref_02.phpt new file mode 100644 index 0000000000000..b056a80ce7d12 --- /dev/null +++ b/ext/zend_test/tests/observer_retval_by_ref_02.phpt @@ -0,0 +1,34 @@ +--TEST-- +Observer: Retvals by reference are observable that are: IS_TMP_VAR +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + +Notice: Only variable references should be returned by reference in %s on line %d + + + +Notice: Only variable references should be returned by reference in %s on line %d + +Done + diff --git a/ext/zend_test/tests/observer_retval_by_ref_03.phpt b/ext/zend_test/tests/observer_retval_by_ref_03.phpt new file mode 100644 index 0000000000000..50fe23add1ff9 --- /dev/null +++ b/ext/zend_test/tests/observer_retval_by_ref_03.phpt @@ -0,0 +1,42 @@ +--TEST-- +Observer: Retvals by reference are observable that are: IS_VAR, ZEND_RETURNS_FUNCTION +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + + + + +Notice: Only variable references should be returned by reference in %s on line %d + + + + + +Notice: Only variable references should be returned by reference in %s on line %d + +Done + From 836ef0b0e332840ff72907e6892bc9c81f6a5df8 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Thu, 12 Nov 2020 14:07:40 -0800 Subject: [PATCH 3/9] Call observer end handler before unused refcounted IS_VAR is freed --- Zend/zend_vm_def.h | 4 +-- Zend/zend_vm_execute.h | 40 ++++++++++----------- ext/zend_test/tests/observer_retval_04.phpt | 12 +++++++ 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cae91a423e9c5..e83e865e9ce75 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4251,14 +4251,14 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) ZEND_OBSERVER_SAVE_OPLINE(); ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else if (!return_value) { + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else { if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 779493e8a0a20..a28fc9ffe5337 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4030,14 +4030,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } else if (!return_value) { + + if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -4114,14 +4114,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER SAVE_OPLINE(); zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else { if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -18557,14 +18557,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } else if (!return_value) { + + if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -21133,14 +21133,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } else if (!return_value) { + + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -37675,14 +37675,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } else if (!return_value) { + + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -54752,14 +54752,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (!return_value) { + + if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -54837,14 +54837,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) SAVE_OPLINE(); zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else { if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -56382,14 +56382,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (!return_value) { + + if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -56691,14 +56691,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (!return_value) { + + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -57816,14 +57816,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (!return_value) { + + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } - - } else { if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(return_value, retval_ptr); diff --git a/ext/zend_test/tests/observer_retval_04.phpt b/ext/zend_test/tests/observer_retval_04.phpt index 2e69857fb426b..883dd85498fb4 100644 --- a/ext/zend_test/tests/observer_retval_04.phpt +++ b/ext/zend_test/tests/observer_retval_04.phpt @@ -21,6 +21,13 @@ function foo() { $res = foo(); // Retval used foo(); // Retval unused +function bar($what) { + return 'This gets ' . $what . ' in the return handler when unused'; // Refcounted + IS_VAR +} + +$res = bar('freed'); // Retval used +bar('freed'); // Retval unused + echo 'Done' . PHP_EOL; ?> --EXPECTF-- @@ -36,5 +43,10 @@ echo 'Done' . PHP_EOL; + + + + + Done From d29998db6afc234eecc5b46206d8a5e21c3bd55f Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Thu, 12 Nov 2020 14:44:50 -0800 Subject: [PATCH 4/9] Pass correct retval from generator on uncaught exception --- Zend/zend_vm_def.h | 12 ++++++++---- Zend/zend_vm_execute.h | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e83e865e9ce75..77b11733694ae 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7719,15 +7719,19 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca } /* Uncaught exception */ - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); - } - cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, &generator->retval); + } + cleanup_live_vars(execute_data, op_num, 0); zend_generator_close(generator, 1); ZEND_VM_RETURN(); } else { + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, EX(return_value)); + } + cleanup_live_vars(execute_data, op_num, 0); /* We didn't execute RETURN, and have to initialize return_value */ if (EX(return_value)) { ZVAL_UNDEF(EX(return_value)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a28fc9ffe5337..18ba98c671361 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2904,15 +2904,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try } /* Uncaught exception */ - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); - } - cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, &generator->retval); + } + cleanup_live_vars(execute_data, op_num, 0); zend_generator_close(generator, 1); ZEND_VM_RETURN(); } else { + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, EX(return_value)); + } + cleanup_live_vars(execute_data, op_num, 0); /* We didn't execute RETURN, and have to initialize return_value */ if (EX(return_value)) { ZVAL_UNDEF(EX(return_value)); From 93320954da15a213bdf746d78d9613b33889b298 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Mon, 16 Nov 2020 10:28:45 -0800 Subject: [PATCH 5/9] Revert "Pass correct retval from generator on uncaught exception" This reverts commit d29998db6afc234eecc5b46206d8a5e21c3bd55f. --- Zend/zend_vm_def.h | 12 ++++-------- Zend/zend_vm_execute.h | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 77b11733694ae..e83e865e9ce75 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7719,19 +7719,15 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca } /* Uncaught exception */ + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, EX(return_value)); + } + cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, &generator->retval); - } - cleanup_live_vars(execute_data, op_num, 0); zend_generator_close(generator, 1); ZEND_VM_RETURN(); } else { - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); - } - cleanup_live_vars(execute_data, op_num, 0); /* We didn't execute RETURN, and have to initialize return_value */ if (EX(return_value)) { ZVAL_UNDEF(EX(return_value)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 18ba98c671361..a28fc9ffe5337 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2904,19 +2904,15 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try } /* Uncaught exception */ + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, EX(return_value)); + } + cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, &generator->retval); - } - cleanup_live_vars(execute_data, op_num, 0); zend_generator_close(generator, 1); ZEND_VM_RETURN(); } else { - if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); - } - cleanup_live_vars(execute_data, op_num, 0); /* We didn't execute RETURN, and have to initialize return_value */ if (EX(return_value)) { ZVAL_UNDEF(EX(return_value)); From 95f943a0d54964a6a0c9b88905f6c885a67dcc6a Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Mon, 16 Nov 2020 10:30:15 -0800 Subject: [PATCH 6/9] Pass NULL to end handler on uncaught exception --- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e83e865e9ce75..ddab688fed8d0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7720,7 +7720,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); + zend_observer_fcall_end(execute_data, NULL); } cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a28fc9ffe5337..73af1b9830358 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2905,7 +2905,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { - zend_observer_fcall_end(execute_data, EX(return_value)); + zend_observer_fcall_end(execute_data, NULL); } cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { From 0fa78a50c052a28a373ee1a8cb38130c637253f0 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Mon, 16 Nov 2020 11:01:45 -0800 Subject: [PATCH 7/9] Use retval by ref before it is freed --- Zend/zend_vm_def.h | 7 ++++++- Zend/zend_vm_execute.h | 30 +++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ddab688fed8d0..b64e960159724 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4333,10 +4333,12 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (!EX(return_value)) { + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); FREE_OP1(); } else { if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); break; } @@ -4344,6 +4346,7 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, if (OP1_TYPE == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } break; } @@ -4356,7 +4359,9 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else { + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); FREE_OP1_VAR_PTR(); } break; @@ -4372,10 +4377,10 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } + ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); FREE_OP1_VAR_PTR(); } while (0); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 73af1b9830358..fdbd1935e0e72 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4197,9 +4197,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE retval_ptr = RT_CONSTANT(opline, opline->op1); if (!EX(return_value)) { + } else { if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; } @@ -4207,6 +4209,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE if (IS_CONST == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + } break; } @@ -4219,8 +4222,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + } else { + } break; } @@ -4235,6 +4240,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -4255,10 +4261,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE retval_ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); if (!EX(return_value)) { + zend_observer_fcall_end(execute_data, retval_ptr); FREE_OP(opline->op1_type, opline->op1.var); } else { if (opline->op1_type == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + zend_observer_fcall_end(execute_data, retval_ptr); break; } @@ -4266,6 +4274,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE if (opline->op1_type == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + zend_observer_fcall_end(execute_data, retval_ptr); } break; } @@ -4278,7 +4287,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + zend_observer_fcall_end(execute_data, retval_ptr); } else { + zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } break; @@ -4294,10 +4305,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } + zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } while (0); - zend_observer_fcall_end(execute_data, retval_ptr); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -18639,10 +18650,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (!EX(return_value)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; } @@ -18650,6 +18663,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER if (IS_TMP_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + } break; } @@ -18662,8 +18676,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + } else { + } break; } @@ -18678,6 +18694,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -21215,10 +21232,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (!EX(return_value)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; } @@ -21226,6 +21245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER if (IS_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + } break; } @@ -21238,7 +21258,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } break; @@ -37758,9 +37780,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (!EX(return_value)) { + } else { if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; } @@ -37768,6 +37792,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( if (IS_CV == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } + } break; } @@ -37780,8 +37805,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + } else { + } break; } @@ -37796,6 +37823,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); From 51d8fd9da83fb125f55bcb7ced87f57bdffccbed Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Mon, 16 Nov 2020 11:02:23 -0800 Subject: [PATCH 8/9] Add test for observability during shutdown --- ext/zend_test/tests/observer_shutdown_01.phpt | 44 ++++++++++++++++ ext/zend_test/tests/observer_shutdown_02.phpt | 50 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 ext/zend_test/tests/observer_shutdown_01.phpt create mode 100644 ext/zend_test/tests/observer_shutdown_02.phpt diff --git a/ext/zend_test/tests/observer_shutdown_01.phpt b/ext/zend_test/tests/observer_shutdown_01.phpt new file mode 100644 index 0000000000000..16ea9cef0e227 --- /dev/null +++ b/ext/zend_test/tests/observer_shutdown_01.phpt @@ -0,0 +1,44 @@ +--TEST-- +Observer: Function calls from a shutdown handler are observable +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + +Done: 42 + + +<{closure}> + + + + + + + +Shutdown: 42 + diff --git a/ext/zend_test/tests/observer_shutdown_02.phpt b/ext/zend_test/tests/observer_shutdown_02.phpt new file mode 100644 index 0000000000000..ad6c906585656 --- /dev/null +++ b/ext/zend_test/tests/observer_shutdown_02.phpt @@ -0,0 +1,50 @@ +--TEST-- +Observer: Function calls from a __destruct during shutdown are observable +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- + +--EXPECTF-- + + + + + +Done: 42 + + + + + + + + + + +Shutdown: 42 + From 7b6572f54246c7f25e0642f25c5d1889592acf62 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Mon, 16 Nov 2020 16:25:56 -0800 Subject: [PATCH 9/9] Add observer_retval to observe the return_value --- Zend/zend_vm_def.h | 43 +++---- Zend/zend_vm_execute.h | 283 ++++++++++++++--------------------------- Zend/zend_vm_gen.php | 3 + 3 files changed, 120 insertions(+), 209 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b64e960159724..2932bfbdfaaef 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4239,20 +4239,18 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) USE_OPLINE zval *retval_ptr; zval *return_value; + ZEND_OBSERVER_USE_RETVAL; retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); return_value = EX(return_value); + ZEND_OBSERVER_SET_RETVAL(); if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else if (!return_value) { - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -4267,8 +4265,6 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) Z_ADDREF_P(return_value); } } - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } else if (OP1_TYPE == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4280,8 +4276,6 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -4294,8 +4288,6 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } while (0); } else /* if (OP1_TYPE == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4311,10 +4303,11 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - ZEND_OBSERVER_SAVE_OPLINE(); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } } + ZEND_OBSERVER_SAVE_OPLINE(); + ZEND_OBSERVER_FCALL_END(execute_data, return_value); + ZEND_OBSERVER_FREE_RETVAL(); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -4322,9 +4315,13 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, { USE_OPLINE zval *retval_ptr; + zval *return_value; + ZEND_OBSERVER_USE_RETVAL; SAVE_OPLINE(); + return_value = EX(return_value); + ZEND_OBSERVER_SET_RETVAL(); do { if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR)) || (OP1_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -4332,21 +4329,18 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); - if (!EX(return_value)) { - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); + if (!return_value) { FREE_OP1(); } else { if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (OP1_TYPE == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); } break; } @@ -4357,30 +4351,29 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); FREE_OP1_VAR_PTR(); } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - ZEND_OBSERVER_FCALL_END(execute_data, retval_ptr); FREE_OP1_VAR_PTR(); } while (0); + ZEND_OBSERVER_FCALL_END(execute_data, return_value); + ZEND_OBSERVER_FREE_RETVAL(); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fdbd1935e0e72..0d14ff3bab26d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4021,17 +4021,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -4046,8 +4043,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ Z_ADDREF_P(return_value); } } - - } else if (IS_CONST == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4059,8 +4054,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -4073,8 +4066,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_CONST == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4090,10 +4081,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4102,20 +4094,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER USE_OPLINE zval *retval_ptr; zval *return_value; + zval observer_retval; retval_ptr = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -4130,8 +4120,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER Z_ADDREF_P(return_value); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else if (opline->op1_type == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -4143,8 +4131,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -4157,8 +4143,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } } ZVAL_COPY_VALUE(return_value, retval_ptr); - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } while (0); } else /* if (opline->op1_type == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -4174,10 +4158,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4185,9 +4170,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE { USE_OPLINE zval *retval_ptr; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_CONST & (IS_CONST|IS_TMP_VAR)) || (IS_CONST == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -4195,21 +4183,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = RT_CONSTANT(opline, opline->op1); - if (!EX(return_value)) { - + if (!return_value) { } else { if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_CONST == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - } break; } @@ -4220,29 +4205,27 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4250,9 +4233,13 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE { USE_OPLINE zval *retval_ptr; + zval *return_value; + zval observer_retval; SAVE_OPLINE(); + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; do { if ((opline->op1_type & (IS_CONST|IS_TMP_VAR)) || (opline->op1_type == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -4260,21 +4247,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); - if (!EX(return_value)) { - zend_observer_fcall_end(execute_data, retval_ptr); + if (!return_value) { FREE_OP(opline->op1_type, opline->op1.var); } else { if (opline->op1_type == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - zend_observer_fcall_end(execute_data, retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (opline->op1_type == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - zend_observer_fcall_end(execute_data, retval_ptr); } break; } @@ -4285,30 +4269,29 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - zend_observer_fcall_end(execute_data, retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } while (0); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -18559,17 +18542,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -18584,8 +18564,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA Z_ADDREF_P(return_value); } } - - } else if (IS_TMP_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -18597,8 +18575,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -18611,8 +18587,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -18628,10 +18602,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -18639,9 +18614,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER { USE_OPLINE zval *retval_ptr; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -18649,21 +18627,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); - if (!EX(return_value)) { - + if (!return_value) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_TMP_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - } break; } @@ -18674,29 +18649,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -21141,17 +21114,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -21166,8 +21136,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA Z_ADDREF_P(return_value); } } - - } else if (IS_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -21179,8 +21147,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -21193,8 +21159,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -21210,10 +21174,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -21221,9 +21186,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER { USE_OPLINE zval *retval_ptr; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -21231,21 +21199,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (!EX(return_value)) { - + if (!return_value) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - } break; } @@ -21256,29 +21221,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -37688,17 +37652,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -37713,8 +37674,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN Z_ADDREF_P(return_value); } } - - } else if (IS_CV == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -37726,8 +37685,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -37740,8 +37697,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_CV == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -37757,10 +37712,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -37768,9 +37724,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( { USE_OPLINE zval *retval_ptr; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_CV & (IS_CONST|IS_TMP_VAR)) || (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -37778,21 +37737,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - if (!EX(return_value)) { - + if (!return_value) { } else { if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_CV == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } - } break; } @@ -37803,29 +37759,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); - + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -54771,17 +54725,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -54796,8 +54747,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } - - } else if (IS_CONST == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -54809,8 +54758,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -54823,8 +54770,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_CONST == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -54840,10 +54785,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -54853,20 +54799,18 @@ ZEND_API void execute_ex(zend_execute_data *ex) USE_OPLINE zval *retval_ptr; zval *return_value; + zval observer_retval; retval_ptr = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else if (!return_value) { - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -54881,8 +54825,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } else if (opline->op1_type == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -54894,8 +54836,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, return_value); break; } else { Z_ADDREF_P(retval_ptr); @@ -54908,8 +54848,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } while (0); } else /* if (opline->op1_type == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -54925,10 +54863,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - SAVE_OPLINE(); - zend_observer_fcall_end(execute_data, retval_ptr); } } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; goto zend_leave_helper_SPEC_LABEL; } @@ -56401,17 +56340,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -56426,8 +56362,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } - - } else if (IS_TMP_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -56439,8 +56373,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -56453,8 +56385,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_TMP_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -56470,10 +56400,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -56710,17 +56641,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -56735,8 +56663,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } - - } else if (IS_VAR == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -56748,8 +56674,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -56762,8 +56686,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -56779,10 +56701,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -57835,17 +57758,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); if (return_value) { ZVAL_NULL(return_value); } - - } else if (!return_value) { - - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); @@ -57860,8 +57780,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) Z_ADDREF_P(return_value); } } - - } else if (IS_CV == IS_CV) { do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { @@ -57873,8 +57791,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) gc_possible_root(ref); } ZVAL_NULL(retval_ptr); - - break; } else { Z_ADDREF_P(retval_ptr); @@ -57887,8 +57803,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ZVAL_COPY_VALUE(return_value, retval_ptr); - - } while (0); } else /* if (IS_CV == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { @@ -57904,10 +57818,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else { ZVAL_COPY_VALUE(return_value, retval_ptr); } - - } } + + + goto zend_leave_helper_SPEC_LABEL; } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index f8baea0d053c7..4958189ce4cf4 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -794,6 +794,9 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) ($extra_spec['ISSET'] == 0 ? "\\0" : "opline->extended_value") : "\\0", "/ZEND_OBSERVER_ENABLED/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0", + "/ZEND_OBSERVER_USE_RETVAL/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "zval observer_retval" : "", + "/ZEND_OBSERVER_SET_RETVAL\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "if (!return_value) { return_value = &observer_retval; }" : "", + "/ZEND_OBSERVER_FREE_RETVAL\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }" : "", "/ZEND_OBSERVER_SAVE_OPLINE\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "SAVE_OPLINE()" : "", "/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ? ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)")