Fix use-after-free on error during module evaluation

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 <oleavr@gmail.com>
This commit is contained in:
Saúl Ibarra Corretgé 2023-11-07 22:23:09 +01:00 committed by GitHub
parent a3a57febed
commit 4f02ab8cfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2225,7 +2225,8 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
JSModuleDef *m = list_entry(el, JSModuleDef, link); JSModuleDef *m = list_entry(el, JSModuleDef, link);
if (flag == JS_FREE_MODULE_ALL || if (flag == JS_FREE_MODULE_ALL ||
(flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) || (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); 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); ret_val = js_evaluate_module(ctx, m1);
if (JS_IsException(ret_val)) { if (JS_IsException(ret_val)) {
m->eval_mark = FALSE; m->eval_mark = FALSE;
js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED);
goto clean; goto clean;
} }
if (!JS_IsUndefined(ret_val)) { if (!JS_IsUndefined(ret_val)) {