Skip to content

Commit b26b758

Browse files
MaxKellermanndevnexen
authored andcommitted
ext/opcache/jit: handle zend_jit_find_trace() failures
Commit 6c25413 added the flag ZEND_JIT_EXIT_INVALIDATE which resets the trace handlers in zend_jit_trace_exit(), but forgot to consider that on ZEND_JIT_TRACE_STOP_LINK, this changed handler gets passed to zend_jit_find_trace(), causing it to fail, either by returning 0 (results in bogus data) or by aborting due to ZEND_UNREACHABLE(). In either case, this crashes the PHP process. I'm not quite sure how to fix this multi-threading problem properly; my suggestion is to just fail the zend_jit_trace() call. After all, the whole ZEND_JIT_EXIT_INVALIDATE fix was about reloading modified scripts, so there's probably no point in this pending zend_jit_trace() call.
1 parent a3891d9 commit b26b758

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ PHP NEWS
2424
- Opcache:
2525
. Fix inverted bailout value in zend_runtime_jit() (Max Kellermann).
2626
. Fix access to uninitialized variable in accel_preload(). (nielsdos)
27+
. Fix zend_jit_find_trace() crashes. (Max Kellermann)
2728

2829
- PHPDBG:
2930
. Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos)

ext/opcache/jit/zend_jit_trace.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,13 @@ static void zend_jit_trace_add_code(const void *start, uint32_t size)
247247
t->code_size = size;
248248
}
249249

250+
/**
251+
* Locate a trace in the #zend_jit_traces array with the specified
252+
* #code_start address.
253+
*
254+
* @return the #zend_jit_traces index or 0 if no such #code_start
255+
* address was found
256+
*/
250257
static uint32_t zend_jit_find_trace(const void *addr)
251258
{
252259
uint32_t i;
@@ -256,7 +263,6 @@ static uint32_t zend_jit_find_trace(const void *addr)
256263
return i;
257264
}
258265
}
259-
ZEND_UNREACHABLE();
260266
return 0;
261267
}
262268

@@ -6843,6 +6849,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
68436849
const void *timeout_exit_addr = NULL;
68446850

68456851
t->link = zend_jit_find_trace(p->opline->handler);
6852+
if (t->link == 0) {
6853+
/* this can happen if ZEND_JIT_EXIT_INVALIDATE was handled
6854+
* by zend_jit_trace_exit() in another thread after this
6855+
* thread set ZEND_JIT_TRACE_STOP_LINK in zend_jit_trace_execute();
6856+
* ZEND_JIT_EXIT_INVALIDATE resets the opline handler to one of
6857+
* the "_counter_handler" functions, and these are not registered
6858+
* tracer functions */
6859+
goto jit_failure;
6860+
}
68466861
if ((zend_jit_traces[t->link].flags & ZEND_JIT_TRACE_USES_INITIAL_IP)
68476862
&& !zend_jit_set_ip(&dasm_state, p->opline)) {
68486863
goto jit_failure;

0 commit comments

Comments
 (0)