Files
eternalwrt-mt798x/package/utils/ucode/patches/102-compiler-prevent-unbounded-recompilation-on-failed-m.patch
T
Felix Fietkau 7987b1f799 ucode: fix two compiler issues
- When working with deeply nested imports, compile errors led to long
  error messages or complete hangs by compiling the same module over
  and over again.
- Fix for a function expression scope issue.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-07 10:46:12 +02:00

54 lines
2.1 KiB
Diff

From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 6 Jul 2026 11:12:32 +0200
Subject: [PATCH] compiler: prevent unbounded recompilation on failed
module imports
A source's exports.offset of -1 marks a module whose compilation has been
entered but not completed. When a module failed to compile, uc_compiler_finish
freed its function and the error cascaded up through the importers via error
recovery, leaving each involved source at offset -1 with its function gone. The
re-entry guard only recognised an in-progress module by finding its function, so
those freed modules were recompiled again on every subsequent import. Across a
wide import graph this recompilation multiplies and the compiler appears to hang.
Detect the offset -1 marker directly instead of relying on the presence of a
function: report a circular dependency when the function is still around, and
propagate the failure otherwise, rather than recursing into the module again.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/compiler.c
+++ b/compiler.c
@@ -3479,15 +3479,26 @@ uc_compiler_compile_module_source(uc_com
uc_program_function_foreach(compiler->program, fn) {
if (uc_program_function_source(fn) == source) {
- if (source->exports.offset == (size_t)-1)
- uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
- "Circular dependency");
-
loaded = true;
break;
}
}
+ /* An offset of -1 marks a source whose compilation was entered but not yet
+ * completed. Re-entering it is either a circular dependency (its function is
+ * still present) or a module whose earlier compilation failed and freed its
+ * function. Recompiling in either case recurses without bound across a large
+ * import graph, so report the cycle and propagate the failure instead. */
+ if (source->exports.offset == (size_t)-1) {
+ if (loaded)
+ uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
+ "Circular dependency");
+ else if (errp)
+ xasprintf(errp, "Module previously failed to compile\n");
+
+ return false;
+ }
+
if (!loaded) {
/* We do not yet support linking precompiled modules at compile time,
turn static import operation into dynamic load one. */