Skip to content

Commit 97b97ae

Browse files
authored
Package fetch: add executable detection for Mach-O file headers (#21555)
1 parent b31a2c9 commit 97b97ae

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

src/Package/Fetch.zig

+31-10
Original file line numberDiff line numberDiff line change
@@ -1789,12 +1789,9 @@ test {
17891789
_ = UnpackResult;
17901790
}
17911791

1792-
// Detects executable header: ELF magic header or shebang line.
1792+
// Detects executable header: ELF or Macho-O magic header or shebang line.
17931793
const FileHeader = struct {
1794-
const elf_magic = std.elf.MAGIC;
1795-
const shebang = "#!";
1796-
1797-
header: [@max(elf_magic.len, shebang.len)]u8 = undefined,
1794+
header: [4]u8 = undefined,
17981795
bytes_read: usize = 0,
17991796

18001797
pub fn update(self: *FileHeader, buf: []const u8) void {
@@ -1804,22 +1801,46 @@ const FileHeader = struct {
18041801
self.bytes_read += n;
18051802
}
18061803

1804+
fn isScript(self: *FileHeader) bool {
1805+
const shebang = "#!";
1806+
return std.mem.eql(u8, self.header[0..@min(self.bytes_read, shebang.len)], shebang);
1807+
}
1808+
1809+
fn isElf(self: *FileHeader) bool {
1810+
const elf_magic = std.elf.MAGIC;
1811+
return std.mem.eql(u8, self.header[0..@min(self.bytes_read, elf_magic.len)], elf_magic);
1812+
}
1813+
1814+
fn isMachO(self: *FileHeader) bool {
1815+
if (self.bytes_read < 4) return false;
1816+
const magic_number = std.mem.readInt(u32, &self.header, builtin.cpu.arch.endian());
1817+
return magic_number == std.macho.MH_MAGIC or
1818+
magic_number == std.macho.MH_MAGIC_64 or
1819+
magic_number == std.macho.FAT_MAGIC or
1820+
magic_number == std.macho.FAT_MAGIC_64;
1821+
}
1822+
18071823
pub fn isExecutable(self: *FileHeader) bool {
1808-
return std.mem.eql(u8, self.header[0..@min(self.bytes_read, shebang.len)], shebang) or
1809-
std.mem.eql(u8, self.header[0..@min(self.bytes_read, elf_magic.len)], elf_magic);
1824+
return self.isScript() or self.isElf() or self.isMachO();
18101825
}
18111826
};
18121827

18131828
test FileHeader {
18141829
var h: FileHeader = .{};
18151830
try std.testing.expect(!h.isExecutable());
18161831

1817-
h.update(FileHeader.elf_magic[0..2]);
1832+
const elf_magic = std.elf.MAGIC;
1833+
h.update(elf_magic[0..2]);
18181834
try std.testing.expect(!h.isExecutable());
1819-
h.update(FileHeader.elf_magic[2..4]);
1835+
h.update(elf_magic[2..4]);
1836+
try std.testing.expect(h.isExecutable());
1837+
1838+
h.update(elf_magic[2..4]);
18201839
try std.testing.expect(h.isExecutable());
18211840

1822-
h.update(FileHeader.elf_magic[2..4]);
1841+
const macho64_magic_bytes = [_]u8{ 0xCF, 0xFA, 0xED, 0xFE };
1842+
h.bytes_read = 0;
1843+
h.update(&macho64_magic_bytes);
18231844
try std.testing.expect(h.isExecutable());
18241845
}
18251846

0 commit comments

Comments
 (0)