[lld] [lld][macho] Fix segfault while processing malformed object file. (PR #167025)

Prabhu Rajasekaran via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 11 11:59:58 PST 2025


https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/167025

>From e1ced6fbe18191dc2ac70ec1e9e3387a09140dac Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 7 Nov 2025 13:46:44 -0800
Subject: [PATCH 1/6] [lld][macho] Fix segfault while processing malformed
 object file.

---
 lld/MachO/InputFiles.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 20e4a1d755229..add59272d9f67 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -808,6 +808,11 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
       continue;
 
     if ((sym.n_type & N_TYPE) == N_SECT) {
+      if (sym.n_sect == 0) {
+        error("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+              toString(this) + " has an invalid section index of 0");
+        llvm_unreachable("Section symbol without an associated section.");
+      }
       Subsections &subsections = sections[sym.n_sect - 1]->subsections;
       // parseSections() may have chosen not to parse this section.
       if (subsections.empty())

>From 5e2c87b42bc5b0d0eefb1ac5a1476ff80aef59e8 Mon Sep 17 00:00:00 2001
From: Prabhu Rajasekaran <prabhukrllvm at gmail.com>
Date: Mon, 10 Nov 2025 08:28:19 -0800
Subject: [PATCH 2/6] Emit fatal error instead of using error llvm_unreachable.

Co-authored-by: Ellis Hoag <ellis.sparky.hoag at gmail.com>
---
 lld/MachO/InputFiles.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index add59272d9f67..a3e5f72724009 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -809,9 +809,8 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
 
     if ((sym.n_type & N_TYPE) == N_SECT) {
       if (sym.n_sect == 0) {
-        error("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+        fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
               toString(this) + " has an invalid section index of 0");
-        llvm_unreachable("Section symbol without an associated section.");
       }
       Subsections &subsections = sections[sym.n_sect - 1]->subsections;
       // parseSections() may have chosen not to parse this section.

>From d077666c30bb98398c2a63c0f6eb1bfbc3c43195 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 10 Nov 2025 15:43:13 -0800
Subject: [PATCH 3/6] Add regression test.

---
 .../handle-invalid-section-reference.test     | 128 ++++++++++++++++++
 1 file changed, 128 insertions(+)
 create mode 100644 lld/test/MachO/handle-invalid-section-reference.test

diff --git a/lld/test/MachO/handle-invalid-section-reference.test b/lld/test/MachO/handle-invalid-section-reference.test
new file mode 100644
index 0000000000000..e0dabbf6c1711
--- /dev/null
+++ b/lld/test/MachO/handle-invalid-section-reference.test
@@ -0,0 +1,128 @@
+# REQUIRES: aarch64
+
+## This is a regression test which makes sure that when there is an invalid section index
+## associated with a section symbol, the linker does not segfault.
+
+## Test YAML content was created using the following steps
+## 1. Create an object file from the following assembly 
+##     `llvm-mc -filetype=obj -triple=arm64-apple-darwin symbol.s -o symbol.o`
+##
+##     .text
+##     .section __TEST,__mystuff
+##     .globl _mysec
+## _mysec:
+##     .byte 0xC3
+##
+## 2. Use obj2yaml to convert object file to yaml
+##    `obj2yaml symbol.o -o symbol.yaml`
+##
+## 3. Manually set n_sect value of ltmp1 symbol to 0 instead of 1.
+##
+
+# RUN: yaml2obj %s -o %t
+# RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
+
+# FATAL: error: Section symbol ltmp0 in {{.*}} has an invalid section index [0]
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x100000C
+  cpusubtype:      0x0
+  filetype:        0x1
+  ncmds:           3
+  sizeofcmds:      336
+  flags:           0x0
+  reserved:        0x0
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         ''
+    vmaddr:          0
+    vmsize:          1
+    fileoff:         368
+    filesize:        1
+    maxprot:         7
+    initprot:        7
+    nsects:          2
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0
+        size:            0
+        offset:          0x170
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x80000000
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         ''
+      - sectname:        __mystuff
+        segname:         __TEST
+        addr:            0x0
+        size:            1
+        offset:          0x170
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         C3
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          376
+    nsyms:           3
+    stroff:          424
+    strsize:         24
+  - cmd:             LC_DYSYMTAB
+    cmdsize:         80
+    ilocalsym:       0
+    nlocalsym:       2
+    iextdefsym:      2
+    nextdefsym:      1
+    iundefsym:       3
+    nundefsym:       0
+    tocoff:          0
+    ntoc:            0
+    modtaboff:       0
+    nmodtab:         0
+    extrefsymoff:    0
+    nextrefsyms:     0
+    indirectsymoff:  0
+    nindirectsyms:   0
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+LinkEditData:
+  NameList:
+    - n_strx:          14
+      n_type:          0xE
+      n_sect:          0
+      n_desc:          0
+      n_value:         0
+    - n_strx:          8
+      n_type:          0xE
+      n_sect:          2
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0xF
+      n_sect:          2
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - _mysec
+    - ltmp1
+    - ltmp0
+    - ''
+    - ''
+    - ''
+    - ''
+...

>From 309e01cb5daf40c875d7ba6851235b6567a20082 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 10 Nov 2025 15:44:44 -0800
Subject: [PATCH 4/6] Nit: Improve error message.

---
 lld/MachO/InputFiles.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index a3e5f72724009..b32f780af6972 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -810,7 +810,7 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
     if ((sym.n_type & N_TYPE) == N_SECT) {
       if (sym.n_sect == 0) {
         fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
-              toString(this) + " has an invalid section index of 0");
+              toString(this) + " has an invalid section index [0]");
       }
       Subsections &subsections = sections[sym.n_sect - 1]->subsections;
       // parseSections() may have chosen not to parse this section.

>From a9e11491a8e96e2efc2b14ec858089278ad59ed1 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 10 Nov 2025 16:09:36 -0800
Subject: [PATCH 5/6] Test for section index larger than section size.

---
 lld/MachO/InputFiles.cpp                      |   7 +
 ...dle-invalid-section-reference-too-big.test | 128 ++++++++++++++++++
 ...andle-invalid-section-reference-zero.test} |   0
 3 files changed, 135 insertions(+)
 create mode 100644 lld/test/MachO/handle-invalid-section-reference-too-big.test
 rename lld/test/MachO/{handle-invalid-section-reference.test => handle-invalid-section-reference-zero.test} (100%)

diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index b32f780af6972..f5f3af038badd 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -812,6 +812,13 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
         fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
               toString(this) + " has an invalid section index [0]");
       }
+      if (sym.n_sect > sections.size()) {
+        fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+              toString(this) + " has an invalid section index [" +
+              Twine(static_cast<unsigned>(sym.n_sect)) +
+              "] greater than the total number of sections [" +
+              Twine(sections.size()) + "].");
+      }
       Subsections &subsections = sections[sym.n_sect - 1]->subsections;
       // parseSections() may have chosen not to parse this section.
       if (subsections.empty())
diff --git a/lld/test/MachO/handle-invalid-section-reference-too-big.test b/lld/test/MachO/handle-invalid-section-reference-too-big.test
new file mode 100644
index 0000000000000..da7b93a7753f2
--- /dev/null
+++ b/lld/test/MachO/handle-invalid-section-reference-too-big.test
@@ -0,0 +1,128 @@
+# REQUIRES: aarch64
+
+## This is a regression test which makes sure that when there is an invalid section index
+## associated with a section symbol, the linker does not segfault.
+
+## Test YAML content was created using the following steps
+## 1. Create an object file from the following assembly 
+##     `llvm-mc -filetype=obj -triple=arm64-apple-darwin symbol.s -o symbol.o`
+##
+##     .text
+##     .section __TEST,__mystuff
+##     .globl _mysec
+## _mysec:
+##     .byte 0xC3
+##
+## 2. Use obj2yaml to convert object file to yaml
+##    `obj2yaml symbol.o -o symbol.yaml`
+##
+## 3. Manually set n_sect value of ltmp1 symbol to 10 which is greater than the number of sections 2.
+##
+
+# RUN: yaml2obj %s -o %t
+# RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
+
+# FATAL: error: Section symbol ltmp0 in {{.*}} has an invalid section index [10] greater than the total number of sections [2].
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x100000C
+  cpusubtype:      0x0
+  filetype:        0x1
+  ncmds:           3
+  sizeofcmds:      336
+  flags:           0x0
+  reserved:        0x0
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         ''
+    vmaddr:          0
+    vmsize:          1
+    fileoff:         368
+    filesize:        1
+    maxprot:         7
+    initprot:        7
+    nsects:          2
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0
+        size:            0
+        offset:          0x170
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x80000000
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         ''
+      - sectname:        __mystuff
+        segname:         __TEST
+        addr:            0x0
+        size:            1
+        offset:          0x170
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         C3
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          376
+    nsyms:           3
+    stroff:          424
+    strsize:         24
+  - cmd:             LC_DYSYMTAB
+    cmdsize:         80
+    ilocalsym:       0
+    nlocalsym:       2
+    iextdefsym:      2
+    nextdefsym:      1
+    iundefsym:       3
+    nundefsym:       0
+    tocoff:          0
+    ntoc:            0
+    modtaboff:       0
+    nmodtab:         0
+    extrefsymoff:    0
+    nextrefsyms:     0
+    indirectsymoff:  0
+    nindirectsyms:   0
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+LinkEditData:
+  NameList:
+    - n_strx:          14
+      n_type:          0xE
+      n_sect:          10
+      n_desc:          0
+      n_value:         0
+    - n_strx:          8
+      n_type:          0xE
+      n_sect:          2
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0xF
+      n_sect:          2
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - _mysec
+    - ltmp1
+    - ltmp0
+    - ''
+    - ''
+    - ''
+    - ''
+...
diff --git a/lld/test/MachO/handle-invalid-section-reference.test b/lld/test/MachO/handle-invalid-section-reference-zero.test
similarity index 100%
rename from lld/test/MachO/handle-invalid-section-reference.test
rename to lld/test/MachO/handle-invalid-section-reference-zero.test

>From 6ec35a9bd309e6a9d0b329c3e2fb481584cf9a5d Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 11 Nov 2025 11:59:19 -0800
Subject: [PATCH 6/6] Fix the error messages as suggested.

---
 lld/MachO/InputFiles.cpp                                    | 6 +++---
 .../MachO/handle-invalid-section-reference-too-big.test     | 2 +-
 lld/test/MachO/handle-invalid-section-reference-zero.test   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index f5f3af038badd..d0128d03a9eab 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -809,15 +809,15 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
 
     if ((sym.n_type & N_TYPE) == N_SECT) {
       if (sym.n_sect == 0) {
-        fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+        fatal("section symbol " + StringRef(strtab + sym.n_strx) + " in " +
               toString(this) + " has an invalid section index [0]");
       }
       if (sym.n_sect > sections.size()) {
-        fatal("Section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+        fatal("section symbol " + StringRef(strtab + sym.n_strx) + " in " +
               toString(this) + " has an invalid section index [" +
               Twine(static_cast<unsigned>(sym.n_sect)) +
               "] greater than the total number of sections [" +
-              Twine(sections.size()) + "].");
+              Twine(sections.size()) + "]");
       }
       Subsections &subsections = sections[sym.n_sect - 1]->subsections;
       // parseSections() may have chosen not to parse this section.
diff --git a/lld/test/MachO/handle-invalid-section-reference-too-big.test b/lld/test/MachO/handle-invalid-section-reference-too-big.test
index da7b93a7753f2..1642d63e50af4 100644
--- a/lld/test/MachO/handle-invalid-section-reference-too-big.test
+++ b/lld/test/MachO/handle-invalid-section-reference-too-big.test
@@ -22,7 +22,7 @@
 # RUN: yaml2obj %s -o %t
 # RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
 
-# FATAL: error: Section symbol ltmp0 in {{.*}} has an invalid section index [10] greater than the total number of sections [2].
+# FATAL: error: section symbol ltmp0 in {{.*}} has an invalid section index [10] greater than the total number of sections [2]
 
 --- !mach-o
 FileHeader:
diff --git a/lld/test/MachO/handle-invalid-section-reference-zero.test b/lld/test/MachO/handle-invalid-section-reference-zero.test
index e0dabbf6c1711..ab636705198e5 100644
--- a/lld/test/MachO/handle-invalid-section-reference-zero.test
+++ b/lld/test/MachO/handle-invalid-section-reference-zero.test
@@ -22,7 +22,7 @@
 # RUN: yaml2obj %s -o %t
 # RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
 
-# FATAL: error: Section symbol ltmp0 in {{.*}} has an invalid section index [0]
+# FATAL: error: section symbol ltmp0 in {{.*}} has an invalid section index [0]
 
 --- !mach-o
 FileHeader:



More information about the llvm-commits mailing list