authorgravatar for fabioarnold@me.comFabio Arnold <fabioarnold@me.com> 2025-01-21 20:48:19+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-01-21 11:48:19-08:00
log97b97ae6202811e207196920018c3b9610957f90
tree66d43bb0ca28d6830f868bfd6110d44a85bc0fcd
parentb31a2c95550e0fd6ee0b1e8908fad69d364ce6ab
signaturebadge-check Signed by PGP key B5690EEEBB952194

Package fetch: add executable detection for Mach-O file headers (#21555)


1 files changed, 31 insertions(+), 10 deletions(-)

src/Package/Fetch.zig+31-10
......@@ -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.
17931793const 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,9 +1801,27 @@ 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
......@@ -1814,12 +1829,18 @@ 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