[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