[lld] [lld][macho] Error out gracefully when offset is outside literal section (PR #164660)

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 22 10:49:46 PDT 2025


https://github.com/int3 updated https://github.com/llvm/llvm-project/pull/164660

>From b4dc8dbd3aeb5e5dca1f56cefcde2edc86a1f4a6 Mon Sep 17 00:00:00 2001
From: Jez Ng <me at jezng.com>
Date: Wed, 22 Oct 2025 12:55:44 -0400
Subject: [PATCH] [lld][macho] Error out gracefully when offset is outside
 literal section

We typically shouldn't get this, but when we do (e.g. in #139439) we should
error out gracefully instead of crashing.

Note that we are stricter than ld64 here; ld64 appears to be able to handle
section offsets that point outside literal sections if the end result is a
valid pointer to another section in the input object file. Supporting this
would probably be a pain given our current design, and it seems like enough of
an edge case that it's onot worth it.
---
 lld/MachO/InputSection.cpp           |  3 ++
 lld/test/MachO/invalid/bad-offsets.s | 45 ++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)
 create mode 100644 lld/test/MachO/invalid/bad-offsets.s

diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index b173e14cc86a8..2b2d28ef63e2d 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -348,6 +348,9 @@ WordLiteralInputSection::WordLiteralInputSection(const Section &section,
 }
 
 uint64_t WordLiteralInputSection::getOffset(uint64_t off) const {
+  if (off >= data.size())
+    fatal(toString(this) + ": offset is outside the section");
+
   auto *osec = cast<WordLiteralSection>(parent);
   const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data());
   switch (sectionType(getFlags())) {
diff --git a/lld/test/MachO/invalid/bad-offsets.s b/lld/test/MachO/invalid/bad-offsets.s
new file mode 100644
index 0000000000000..e1244ee501960
--- /dev/null
+++ b/lld/test/MachO/invalid/bad-offsets.s
@@ -0,0 +1,45 @@
+## Test that we properly detect and report out-of-bounds offsets in literal sections.
+## We're intentionally testing fatal errors (for malformed input files), and
+## fatal errors aren't supported for testing when main is run twice.
+# XFAIL: main-run-twice
+
+# REQUIRES: x86
+# RUN: rm -rf %t; split-file %s %t
+
+## Test WordLiteralInputSection bounds checking
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/word-literal.s -o %t/word-literal.o
+# RUN: not %lld -dylib %t/word-literal.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=WORD
+
+## Test CStringInputSection bounds checking
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/cstring.s -o %t/cstring.o
+# RUN: not %lld -dylib %t/cstring.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CSTRING
+
+# WORD: error: {{.*}}word-literal.o:(__literal4): offset is outside the section
+# CSTRING: error: {{.*}}cstring.o:(__cstring): offset is outside the section
+
+#--- word-literal.s
+.section __TEXT,__literal4,4byte_literals
+L_literal:
+  .long 0x01020304
+
+.text
+.globl _main
+_main:
+  # We use a subtractor expression to force a section relocation. Symbol relocations
+  # don't trigger the error.
+  .long L_literal - _main + 4
+
+.subsections_via_symbols
+
+#--- cstring.s
+## Create a cstring section with a reference that points past the end
+.cstring
+L_str:
+  .asciz "foo"
+
+.text
+.globl _main
+_main:
+  .long L_str - _main + 4
+
+.subsections_via_symbols
\ No newline at end of file



More information about the llvm-commits mailing list