Skip to content

Commit 1857805

Browse files
committed
[yaml2obj][MachO] Fix crash from integer underflow with invalid cmdsize
yaml2obj would crash when processing Mach-O load commands with cmdsize smaller than the actual structure size e.g. LC_SEGMENT_64 with cmdsize=56 instead of 72. The crash occurred due to integer underflow when calculating padding: cmdsize - BytesWritten wraps to a large value when negative, causing a massive allocation attempt.
1 parent c528f60 commit 1857805

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

llvm/lib/ObjectYAML/MachOEmitter.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,15 @@ void MachOWriter::writeLoadCommands(raw_ostream &OS) {
285285

286286
// Fill remaining bytes with 0. This will only get hit in partially
287287
// specified test cases.
288-
auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten;
288+
// Prevent integer underflow if BytesWritten exceeds cmdsize.
289+
if (BytesWritten > LC.Data.load_command_data.cmdsize) {
290+
errs() << "warning: load command " << LC.Data.load_command_data.cmd
291+
<< " cmdsize too small (" << LC.Data.load_command_data.cmdsize
292+
<< " bytes) for actual size (" << BytesWritten << " bytes)\n";
293+
}
294+
auto BytesRemaining = (BytesWritten < LC.Data.load_command_data.cmdsize)
295+
? LC.Data.load_command_data.cmdsize - BytesWritten
296+
: 0;
289297
if (BytesRemaining > 0) {
290298
ZeroFillBytes(OS, BytesRemaining);
291299
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
## Test that yaml2obj handles cmdsize that is too small for LC_SEGMENT_64
2+
## without crashing (due to integer underflow).
3+
4+
# RUN: yaml2obj %s -o %t 2>&1 | FileCheck %s --check-prefix=WARNING
5+
# RUN: not llvm-readobj --file-headers %t 2>&1 | FileCheck %s --check-prefix=MALFORMED
6+
7+
# WARNING: warning: load command 25 cmdsize too small (56 bytes) for actual size (72 bytes)
8+
9+
# MALFORMED: error: {{.*}}: truncated or malformed object (load command 0 LC_SEGMENT_64 cmdsize too small)
10+
11+
--- !mach-o
12+
FileHeader:
13+
magic: 0xFEEDFACF
14+
cputype: 0x01000007
15+
cpusubtype: 0x00000003
16+
filetype: 0x00000001
17+
ncmds: 1
18+
sizeofcmds: 56
19+
flags: 0x00002000
20+
reserved: 0x00000000
21+
LoadCommands:
22+
- cmd: LC_SEGMENT_64
23+
cmdsize: 56 ## Should be 72 for LC_SEGMENT_64
24+
segname: '__TEXT'
25+
vmaddr: 0x1000
26+
vmsize: 0x10
27+
fileoff: 0
28+
filesize: 0
29+
maxprot: 7
30+
initprot: 5
31+
nsects: 0
32+
flags: 0
33+
...

0 commit comments

Comments
 (0)