From 7d49f083d7d4dd77d244cc3e7cae9a7db7d9cfe4 Mon Sep 17 00:00:00 2001 From: Nick Vatamaniuc Date: Thu, 20 Nov 2025 15:08:07 -0500 Subject: [PATCH] Fix worker port use-after-free In #462 during exit we call `js_std_free_handlers()` then `JS_FreeRuntime()`. `js_std_free_handlers()` frees the `JSThreadState` memory. However, later in `JS_FreeRuntime()` we run GC, which runs `js_worker_finalizer` and that accesses the port list from the already freed `JSThreadState`, so it results in a use-after-free error. To fix it try to run GC in `js_std_free_handlers()` just before before cleaning and freeing `JSThreadState`. Fix #462 --- quickjs-libc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quickjs-libc.c b/quickjs-libc.c index 54a7a15..10b17ea 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -4116,6 +4116,11 @@ void js_std_free_handlers(JSRuntime *rt) JSThreadState *ts = JS_GetRuntimeOpaque(rt); struct list_head *el, *el1; + /* Run GC before freeing the JSThreadState. The JSThreadState */ + /* contains the worker port_list and JS_FreeRuntime migth reference */ + /* it when it does worker defered finalization in JS_FreeRuntime */ + JS_RunGC(rt); + list_for_each_safe(el, el1, &ts->os_rw_handlers) { JSOSRWHandler *rh = list_entry(el, JSOSRWHandler, link); free_rw_handler(rt, rh);