[lld] [LLD] Fix crash on parsing ':ALIGN' in linker script (PR #146723)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 2 08:25:07 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Parth (parth-07)
<details>
<summary>Changes</summary>
The linker was crashing due to stack overflow when parsing ':ALIGN' in an output section description. This commit fixes the linker script parser so that the crash does not happen.
The root cause of the stack overflow is how we parse expressions (readExpr) in linker script and the behavior of ScriptLexer::expect(...) utility. ScriptLexer::expect does not do anything if errors have already been encountered during linker script parsing. In particular, it never increments the current token position in the script file, even if the current token is the same as the expected token. This causes an infinite call cycle on parsing an expression such as '(4096)' when an error has already been encountered.
readExpr() calls readPrimary()
readPrimary() calls readParenExpr()
readParenExpr():
expect("("); // no-op, current token still points to '('
Expression *E = readExpr(); // The cycle continues...
Closes #<!-- -->146722
---
Full diff: https://github.com/llvm/llvm-project/pull/146723.diff
2 Files Affected:
- (modified) lld/ELF/ScriptParser.cpp (+3)
- (modified) lld/test/ELF/linkerscript/align-section.test (+16-1)
``````````diff
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 593d5636f2455..58b4239c4aefd 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1229,6 +1229,9 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
// This is an operator-precedence parser to parse a linker
// script expression.
Expr ScriptParser::readExpr() {
+ // Do not try to read expression if an error has already been encountered.
+ if (atEOF())
+ return {};
// Our lexer is context-aware. Set the in-expression bit so that
// they apply different tokenization rules.
SaveAndRestore saved(lexState, State::Expr);
diff --git a/lld/test/ELF/linkerscript/align-section.test b/lld/test/ELF/linkerscript/align-section.test
index 7a28fef2076ed..db99dc82f5514 100644
--- a/lld/test/ELF/linkerscript/align-section.test
+++ b/lld/test/ELF/linkerscript/align-section.test
@@ -1,7 +1,22 @@
# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t
+
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
-# RUN: ld.lld -o %t --script %s %t.o -shared
+# RUN: ld.lld -o %t.1.out --script %t/a.t %t.o -shared
# lld shouldn't crash.
+#--- a.t
SECTIONS { .foo : ALIGN(2M) {} }
+
+#--- b.t
+SECTIONS
+{
+ S :ALIGN(4096) {}
+}
+
+# RUN: not ld.lld -o /dev/null --script %t/b.t 2>&1 | FileCheck %s
+
+CHECK: error: {{.*}}b.t:3: malformed number: :
+CHECK: >>> S :ALIGN(4096) {}
+CHECK: >>>
``````````
</details>
https://github.com/llvm/llvm-project/pull/146723
More information about the llvm-commits
mailing list