- 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>
54 lines
2.1 KiB
Diff
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. */
|