[lld] 923a3cc - [LLD] Fix crash on parsing ':ALIGN' in linker script (#146723)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 6 10:22:54 PDT 2025


Author: Parth
Date: 2025-07-06T10:22:50-07:00
New Revision: 923a3cc160a14e61bd2847f9b011bb4d6ce4fc71

URL: https://github.com/llvm/llvm-project/commit/923a3cc160a14e61bd2847f9b011bb4d6ce4fc71
DIFF: https://github.com/llvm/llvm-project/commit/923a3cc160a14e61bd2847f9b011bb4d6ce4fc71.diff

LOG: [LLD] Fix crash on parsing ':ALIGN' in linker script (#146723)

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

Signed-off-by: Parth Arora <partaror at qti.qualcomm.com>

Added: 
    

Modified: 
    lld/ELF/ScriptParser.cpp
    lld/test/ELF/linkerscript/align-section.test

Removed: 
    


################################################################################
diff  --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 593d5636f2455..ddfa24d9cacf5 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1229,6 +1229,8 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
 // This is an operator-precedence parser to parse a linker
 // script expression.
 Expr ScriptParser::readExpr() {
+  if (atEOF())
+    return []() { return 0; };
   // Our lexer is context-aware. Set the in-expression bit so that
   // they apply 
diff erent 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..1324be24a9328 100644
--- a/lld/test/ELF/linkerscript/align-section.test
+++ b/lld/test/ELF/linkerscript/align-section.test
@@ -1,7 +1,24 @@
 # REQUIRES: x86
-# 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: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o a.o
+# RUN: ld.lld --script a.t a.o -shared
 
 # lld shouldn't crash.
 
+#--- a.t
 SECTIONS { .foo : ALIGN(2M) {} }
+
+# RUN: not ld.lld --script b.t 2>&1 | FileCheck %s --match-full-lines --strict-whitespace
+
+# lld should not crash and report the error properly.
+
+# CHECK:{{.*}} error: b.t:3: malformed number: :
+# CHECK:>>>   S :ALIGN(4096) {}
+# CHECK:>>>     ^
+
+#--- b.t
+SECTIONS
+{
+  S :ALIGN(4096) {}
+}


        


More information about the llvm-commits mailing list