diff --git a/NEWS b/NEWS index aaf02438081a1..072445c5efb58 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,8 @@ PHP NEWS . Fixed bug GH-14267 (opcache.jit=off does not allow enabling JIT at runtime). (ilutov) . Fixed TLS access in JIT on FreeBSD/amd64. (Arnaud) + . Fixed bug GH-13817 (Segmentation fault for enabled observers after pass 4). + (Bob) - Soap: . Fixed bug #47925 (PHPClient can't decompress response). (nielsdos) diff --git a/Zend/Optimizer/compact_vars.c b/Zend/Optimizer/compact_vars.c index a8ef8846deca2..9898714a17c5e 100644 --- a/Zend/Optimizer/compact_vars.c +++ b/Zend/Optimizer/compact_vars.c @@ -18,6 +18,7 @@ #include "Optimizer/zend_optimizer_internal.h" #include "zend_bitset.h" +#include "zend_observer.h" /* This pass removes all CVs and temporaries that are completely unused. It does *not* merge any CVs or TMPs. * This pass does not operate on SSA form anymore. */ @@ -117,7 +118,7 @@ void zend_optimizer_compact_vars(zend_op_array *op_array) { op_array->last_var = num_cvs; } - op_array->T = num_tmps; + op_array->T = num_tmps + ZEND_OBSERVER_ENABLED; // reserve last temporary for observers if enabled free_alloca(vars_map, use_heap2); } diff --git a/Zend/Optimizer/optimize_temp_vars_5.c b/Zend/Optimizer/optimize_temp_vars_5.c index 33d418ffbd99c..de0b189d5dca1 100644 --- a/Zend/Optimizer/optimize_temp_vars_5.c +++ b/Zend/Optimizer/optimize_temp_vars_5.c @@ -26,6 +26,7 @@ #include "zend_execute.h" #include "zend_vm.h" #include "zend_bitset.h" +#include "zend_observer.h" #define INVALID_VAR ((uint32_t)-1) #define GET_AVAILABLE_T() \ @@ -173,5 +174,5 @@ void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_c } zend_arena_release(&ctx->arena, checkpoint); - op_array->T = max + 1; + op_array->T = max + 1 + ZEND_OBSERVER_ENABLED; // reserve last temporary for observers if enabled } diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index f274edb039c17..8a029c8007b85 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -31,7 +31,6 @@ #include "zend_inference.h" #include "zend_dump.h" #include "php.h" -#include "zend_observer.h" #ifndef ZEND_OPTIMIZER_MAX_REGISTERED_PASSES # define ZEND_OPTIMIZER_MAX_REGISTERED_PASSES 32 @@ -1097,8 +1096,6 @@ static void zend_revert_pass_two(zend_op_array *op_array) } #endif - op_array->T -= ZEND_OBSERVER_ENABLED; - op_array->fn_flags &= ~ZEND_ACC_DONE_PASS_TWO; } @@ -1128,8 +1125,6 @@ static void zend_redo_pass_two(zend_op_array *op_array) } #endif - op_array->T += ZEND_OBSERVER_ENABLED; // reserve last temporary for observers if enabled - opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { @@ -1557,12 +1552,6 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l } } - if (ZEND_OBSERVER_ENABLED) { - for (i = 0; i < call_graph.op_arrays_count; i++) { - ++call_graph.op_arrays[i]->T; // ensure accurate temporary count for stack size precalculation - } - } - if (ZEND_OPTIMIZER_PASS_12 & optimization_level) { for (i = 0; i < call_graph.op_arrays_count; i++) { zend_adjust_fcall_stack_size_graph(call_graph.op_arrays[i]); @@ -1578,8 +1567,6 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l zend_recalc_live_ranges(op_array, needs_live_range); } } else { - op_array->T -= ZEND_OBSERVER_ENABLED; // redo_pass_two will re-increment it - zend_redo_pass_two(op_array); if (op_array->live_range) { zend_recalc_live_ranges(op_array, NULL); diff --git a/ext/opcache/tests/gh13817.phpt b/ext/opcache/tests/gh13817.phpt new file mode 100644 index 0000000000000..0e5eb560d46f3 --- /dev/null +++ b/ext/opcache/tests/gh13817.phpt @@ -0,0 +1,51 @@ +--TEST-- +GH-13712 (Segmentation fault for enabled observers after pass 4) +--EXTENSIONS-- +opcache +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.show_output=1 +zend_test.observer.observe_all=1 +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=0x4069 +--FILE-- + +--EXPECTF-- + + + + + + + + +Ok + + + + +