Skip to content

Commit 44e272d

Browse files
committed
Re-land: [MachO] Fixing ub in MachO BinaryFormat
This re-lands r333797 with a fix for big endian systems. Original commit message: This isn't encountered anywhere inside LLVM, so I wrote a test case to expose the issue and verify that it is fixed. The basic problem is that the macho_load_command union contains all load comamnd structs. Load command structs in 32-bit macho files can be 32-bit aligned instead of 64-bit aligned. There are some strange circumstances in which this can be exposed in a 64-bit macho if the load commands are invalid or if a 32-bit aligned load command is used. In the past we've worked around this type of problem with changes like r264232. llvm-svn: 333803
1 parent 157af1a commit 44e272d

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

llvm/include/llvm/BinaryFormat/MachO.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1973,9 +1973,11 @@ const uint32_t PPC_THREAD_STATE_COUNT =
19731973
// Define a union of all load command structs
19741974
#define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data;
19751975

1976-
union macho_load_command {
1976+
LLVM_PACKED_START
1977+
union LLVM_ALIGNAS(4) macho_load_command {
19771978
#include "llvm/BinaryFormat/MachO.def"
19781979
};
1980+
LLVM_PACKED_END
19791981

19801982
} // end namespace MachO
19811983
} // end namespace llvm

llvm/unittests/BinaryFormat/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
44

55
add_llvm_unittest(BinaryFormatTests
66
DwarfTest.cpp
7+
MachOTest.cpp
78
TestFileMagic.cpp
89
)
910

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===- unittest/BinaryFormat/MachOTest.cpp - MachO support tests ----------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "llvm/BinaryFormat/MachO.h"
11+
#include "gtest/gtest.h"
12+
13+
using namespace llvm;
14+
using namespace llvm::MachO;
15+
16+
TEST(MachOTest, UnalignedLC) {
17+
unsigned char Valid32BitMachO[] = {
18+
0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
19+
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
20+
0x85, 0x80, 0x21, 0x01, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
21+
0x5F, 0x5F, 0x50, 0x41, 0x47, 0x45, 0x5A, 0x45, 0x52, 0x4F, 0x00, 0x00,
22+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
23+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25+
0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x4C, 0x49,
26+
0x4E, 0x4B, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27+
0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
28+
0x8C, 0x0B, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
29+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
30+
31+
mach_header *Header =
32+
reinterpret_cast<mach_header *>(Valid32BitMachO);
33+
if (!sys::IsLittleEndianHost)
34+
sys::swapByteOrder(Header->magic);
35+
ASSERT_EQ(Header->magic, MH_MAGIC);
36+
unsigned char *Current = Valid32BitMachO + sizeof(mach_header);
37+
unsigned char *BufferEnd =
38+
Valid32BitMachO + sizeof(mach_header) + Header->sizeofcmds;
39+
while (Current < BufferEnd) {
40+
macho_load_command *LC =
41+
reinterpret_cast<macho_load_command *>(Current);
42+
if (!sys::IsLittleEndianHost)
43+
swapStruct(LC->load_command_data);
44+
ASSERT_EQ(LC->load_command_data.cmd, LC_SEGMENT);
45+
Current += LC->load_command_data.cmdsize;
46+
}
47+
}

0 commit comments

Comments
 (0)