From 4f02ab8cfa0f577318764d7eb788d8c05e894a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Tue, 7 Nov 2023 22:23:09 +0100 Subject: [PATCH] Fix use-after-free on error during module evaluation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit E.g. if during evaluation of module A, we start loading module B and an error occurs. This results in a call to js_free_modules() with JS_FREE_MODULE_NOT_EVALUATED, and since module A isn't yet evaluated, it gets freed prematurely. To solve this we improve js_free_modules() to ensure `eval_mark` is not set. Once js_evaluate_module() returns for module A, it will notice that an exception occurred and call js_free_modules() with JS_FREE_MODULE_NOT_EVALUATED. Since `eval_mark` has been cleared by then, module A gets cleaned up as well. Co-authored-by: Ole André Vadla Ravnås --- quickjs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickjs.c b/quickjs.c index 8006e1e..b6a2df5 100644 --- a/quickjs.c +++ b/quickjs.c @@ -2225,7 +2225,8 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag) JSModuleDef *m = list_entry(el, JSModuleDef, link); if (flag == JS_FREE_MODULE_ALL || (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) || - (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated)) { + (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated + && !m->eval_mark)) { js_free_module_def(ctx, m); } } @@ -28009,6 +28010,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) ret_val = js_evaluate_module(ctx, m1); if (JS_IsException(ret_val)) { m->eval_mark = FALSE; + js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED); goto clean; } if (!JS_IsUndefined(ret_val)) {