spack.util.elf: catch seek errors (#48972)

This commit is contained in:
Harmen Stoppels 2025-02-11 08:52:52 +01:00 committed by GitHub
parent 54210270c8
commit 3909308d5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 6 deletions

View File

@ -201,3 +201,15 @@ def test_drop_redundant_rpath(tmpdir, binary_with_rpaths):
new_rpaths = elf.get_rpaths(binary)
assert set(existing_dirs).issubset(new_rpaths)
assert set(non_existing_dirs).isdisjoint(new_rpaths)
def test_elf_invalid_e_shnum(tmp_path):
# from llvm/test/Object/Inputs/invalid-e_shnum.elf
path = tmp_path / "invalid-e_shnum.elf"
with open(path, "wb") as file:
file.write(
b"\x7fELF\x02\x010000000000\x03\x00>\x0000000000000000000000"
b"\x00\x00\x00\x00\x00\x00\x00\x000000000000@\x000000"
)
with open(path, "rb") as file, pytest.raises(elf.ElfParsingError):
elf.parse_elf(file)

View File

@ -195,7 +195,10 @@ def parse_program_headers(f: BinaryIO, elf: ElfFile) -> None:
elf: ELF file parser data
"""
# Forward to the program header
f.seek(elf.elf_hdr.e_phoff)
try:
f.seek(elf.elf_hdr.e_phoff)
except OSError:
raise ElfParsingError("Could not seek to program header")
# Here we have to make a mapping from virtual address to offset in the file.
ph_fmt = elf.byte_order + ("LLQQQQQQ" if elf.is_64_bit else "LLLLLLLL")
@ -245,7 +248,10 @@ def parse_pt_interp(f: BinaryIO, elf: ElfFile) -> None:
f: file handle
elf: ELF file parser data
"""
f.seek(elf.pt_interp_p_offset)
try:
f.seek(elf.pt_interp_p_offset)
except OSError:
raise ElfParsingError("Could not seek to PT_INTERP entry")
data = read_exactly(f, elf.pt_interp_p_filesz, "Malformed PT_INTERP entry")
elf.pt_interp_str = parse_c_string(data)
@ -264,7 +270,10 @@ def find_strtab_size_at_offset(f: BinaryIO, elf: ElfFile, offset: int) -> int:
"""
section_hdr_fmt = elf.byte_order + ("LLQQQQLLQQ" if elf.is_64_bit else "LLLLLLLLLL")
section_hdr_size = calcsize(section_hdr_fmt)
f.seek(elf.elf_hdr.e_shoff)
try:
f.seek(elf.elf_hdr.e_shoff)
except OSError:
raise ElfParsingError("Could not seek to section header table")
for _ in range(elf.elf_hdr.e_shnum):
data = read_exactly(f, section_hdr_size, "Malformed section header")
sh = SectionHeader(*unpack(section_hdr_fmt, data))
@ -286,7 +295,10 @@ def retrieve_strtab(f: BinaryIO, elf: ElfFile, offset: int) -> bytes:
Returns: file offset
"""
size = find_strtab_size_at_offset(f, elf, offset)
f.seek(offset)
try:
f.seek(offset)
except OSError:
raise ElfParsingError("Could not seek to string table")
return read_exactly(f, size, "Could not read string table")
@ -319,7 +331,10 @@ def parse_pt_dynamic(f: BinaryIO, elf: ElfFile) -> None:
count_runpath = 0
count_strtab = 0
f.seek(elf.pt_dynamic_p_offset)
try:
f.seek(elf.pt_dynamic_p_offset)
except OSError:
raise ElfParsingError("Could not seek to PT_DYNAMIC entry")
# In case of broken ELF files, don't read beyond the advertized size.
for _ in range(elf.pt_dynamic_p_filesz // dynamic_array_size):
@ -478,7 +493,10 @@ def get_interpreter(path: str) -> Optional[str]:
def _delete_dynamic_array_entry(
f: BinaryIO, elf: ElfFile, should_delete: Callable[[int, int], bool]
) -> None:
f.seek(elf.pt_dynamic_p_offset)
try:
f.seek(elf.pt_dynamic_p_offset)
except OSError:
raise ElfParsingError("Could not seek to PT_DYNAMIC entry")
dynamic_array_fmt = elf.byte_order + ("qQ" if elf.is_64_bit else "lL")
dynamic_array_size = calcsize(dynamic_array_fmt)
new_offset = elf.pt_dynamic_p_offset # points to the new dynamic array