[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@qti.qualcomm.com>
This commit is contained in:
Parth
2025-07-06 22:52:50 +05:30
committed by GitHub
parent 9c7320e5d3
commit 923a3cc160
2 changed files with 21 additions and 2 deletions

View File

@@ -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 different tokenization rules.
SaveAndRestore saved(lexState, State::Expr);

View File

@@ -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) {}
}