diff --git a/NEWS b/NEWS index d79257caf334..51d318da68ed 100644 --- a/NEWS +++ b/NEWS @@ -230,6 +230,8 @@ PHP NEWS . Fixed bug GH-24988 (Incorrect opcode range check causes bugs with exceptions in function JIT). (ndossche, Jorg Sowa) . Fix opcache phar check. (ndossche) + . Fixed bug GH-25165 (Tracing JIT loops forever once opcache.jit_buffer_size + is exhausted while compiling side traces). (Ilia Alshanetsky) - OpenSSL: . Fixed build and test compatibility with OpenSSL 4.0 and 4.1. diff --git a/ext/opcache/jit/ir/ir_aarch64.dasc b/ext/opcache/jit/ir/ir_aarch64.dasc index dae5837403dc..c3e88e46e3b4 100644 --- a/ext/opcache/jit/ir/ir_aarch64.dasc +++ b/ext/opcache/jit/ir/ir_aarch64.dasc @@ -6915,6 +6915,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) entry = ctx->code_buffer->pos; entry = (void*)IR_ALIGNED_SIZE(((size_t)(entry)), 16); if (size > (size_t)((char*)ctx->code_buffer->end - (char*)entry)) { + dasm_free(&data.dasm_state); ctx->data = NULL; ctx->status = IR_ERROR_CODE_MEM_OVERFLOW; return NULL; @@ -7057,6 +7058,7 @@ const void *ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_pe entry = code_buffer->pos; entry = (void*)IR_ALIGNED_SIZE(((size_t)(entry)), 16); if (size > (size_t)((char*)code_buffer->end - (char*)entry)) { + dasm_free(&dasm_state); return NULL; } code_buffer->pos = (char*)entry + size; diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index a62e49fc40ed..dee5867108e6 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -12244,6 +12244,7 @@ next_block:; entry = ctx->code_buffer->pos; entry = (void*)IR_ALIGNED_SIZE(((size_t)(entry)), 16); if (size > (size_t)((char*)ctx->code_buffer->end - (char*)entry)) { + dasm_free(&data.dasm_state); ctx->data = NULL; ctx->status = IR_ERROR_CODE_MEM_OVERFLOW; return NULL; @@ -12383,6 +12384,7 @@ const void *ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_pe entry = code_buffer->pos; entry = (void*)IR_ALIGNED_SIZE(((size_t)(entry)), 16); if (size > (size_t)((char*)code_buffer->end - (char*)entry)) { + dasm_free(&dasm_state); return NULL; } code_buffer->pos = (char*)entry + size; diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index b424934e4927..9c54767fc226 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8765,7 +8765,7 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf return 1; /* Lock-free check if the side trace was already JIT-ed or blacklist-ed in another process */ } else if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED)) { - return 0; + return EX(opline) == zend_jit_traces[t->root].opline; } ZEND_ASSERT(EX(func)->type == ZEND_USER_FUNCTION); diff --git a/ext/opcache/tests/jit/gh25165.phpt b/ext/opcache/tests/jit/gh25165.phpt new file mode 100644 index 000000000000..2315243c75e5 --- /dev/null +++ b/ext/opcache/tests/jit/gh25165.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-25165 (Tracing JIT: infinite loop once opcache.jit_buffer_size is exhausted while compiling side traces) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=tracing +opcache.jit_buffer_size=4K +opcache.jit_hot_loop=1 +opcache.jit_hot_func=1 +opcache.jit_hot_return=1 +opcache.jit_hot_side_exit=1 +--FILE-- + +--EXPECT-- +float(232500)