[lld] [ELF] Fix crash when INCLUDE'd linker script ends mid-assignment (PR #192198)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 15 00:07:18 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-lld
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
`readAssignment` builds `commandString` from a `[oldS, curTok)` byte
span. If the expression is read from an INCLUDE'd script whose buffer is
exhausted before the terminator, the two pointers come from different
`MemoryBuffer`s, leading to `std::length_error`.
Fix #<!-- -->190376: Skip the map-file string if the
buffer changed.
---
Full diff: https://github.com/llvm/llvm-project/pull/192198.diff
2 Files Affected:
- (modified) lld/ELF/ScriptParser.cpp (+8-2)
- (added) lld/test/ELF/linkerscript/include-mid-assignment.s (+31)
``````````diff
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 0300b956e6071..c52982d525237 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1157,6 +1157,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
const char *oldS = prevTok.data();
+ const char *oldBufBegin = curBuf.begin;
SymbolAssignment *cmd = nullptr;
bool savedSeenRelroEnd = ctx.script->seenRelroEnd;
const StringRef op = peek();
@@ -1179,8 +1180,13 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
if (cmd) {
cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && ctx.script->seenRelroEnd;
- cmd->commandString = StringRef(oldS, curTok.data() - oldS).str();
- squeezeSpaces(cmd->commandString);
+ // If the inner buffer of an INCLUDE was exhausted while reading the
+ // expression, oldS lives in a popped buffer and the [oldS, curTok) span is
+ // not a valid pointer range.
+ if (curBuf.begin == oldBufBegin) {
+ cmd->commandString = StringRef(oldS, curTok.data() - oldS).str();
+ squeezeSpaces(cmd->commandString);
+ }
expect(";");
}
return cmd;
diff --git a/lld/test/ELF/linkerscript/include-mid-assignment.s b/lld/test/ELF/linkerscript/include-mid-assignment.s
new file mode 100644
index 0000000000000..783e795bb4c77
--- /dev/null
+++ b/lld/test/ELF/linkerscript/include-mid-assignment.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+## When recording `commandString`, an assignment in an INCLUDEd linker script
+## that is missing the trailing ';' must not crash lld. Same for a PROVIDE
+## whose inner buffer is exhausted before the closing ')'.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: not ld.lld a.o -T outer.lds 2>&1 | FileCheck %s
+# RUN: not ld.lld a.o -T outer2.lds 2>&1 | FileCheck %s --check-prefix=CHECK2
+
+# CHECK: error: outer.lds:2: ; expected, but got {{.*}}
+# CHECK2: error: outer2.lds:2: ) expected, but got {{.*}}
+
+#--- outer.lds
+INCLUDE "inc.lds"
+SECTIONS { .text : { *(.text*) } }
+
+#--- inc.lds
+foo = 1
+
+#--- outer2.lds
+INCLUDE "inc2.lds"
+SECTIONS { .text : { *(.text*) } }
+
+#--- inc2.lds
+PROVIDE(bar = 1
+
+#--- a.s
+.globl _start
+_start:
+ ret
``````````
</details>
https://github.com/llvm/llvm-project/pull/192198
More information about the llvm-commits
mailing list