ELF: Tolerate a missing dynamic string table when reading soname and RELRO - #731
ELF: Tolerate a missing dynamic string table when reading soname and RELRO#731zardus wants to merge 1 commit into
Conversation
…RELRO MetaELF.extract_soname() and _get_relro() both walk a dynamic table with an unfiltered iter_tags(), which makes pyelftools resolve the dynamic string table for every tag it yields. An object whose .dynamic section has sh_link 0 has no string table to resolve, and pyelftools reports that with a bare assert rather than an ELFError, so it escaped extract_soname()'s ELFError handler and killed Loader.__init__() and Loader.find_object() outright. Both are best-effort heuristics with a defined "cannot tell" answer, so give it instead of raising. extract_soname() also asks for DT_SONAME specifically, which lets an object that has no soname still fall back to its basename.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head Reproducer, run from a import shutil, struct
from elftools.elf.elffile import ELFFile
shutil.copy("../binaries/tests/x86_64/cpp_qualified_symbols.so", "no_dynstr.so")
with open("no_dynstr.so", "r+b") as f:
e = ELFFile(f)
i = next(i for i, s in enumerate(e.iter_sections()) if s["sh_type"] == "SHT_DYNAMIC")
f.seek(e["e_shoff"] + i * e["e_shentsize"] + 40) # sh_link in Elf64_Shdr
f.write(struct.pack("<I", 0))
f.seek(18) # e_machine -> EM_NONE
f.write(struct.pack("<H", 0))
import cle
cle.Loader("no_dynstr.so", auto_load_libs=False, main_opts={"backend": "elf"})
Notes:
Corpus measurement of the open queue, 2026-08-15 — this change clears none of the class it was filed againstCorrecting the record. The open pull-request queue was scored against 733 objects drawn from a sweep's own failing units (35 error classes, 49 architectures, 16 containers), with each repository's current master as the baseline rather than the revisions the sweep pinned. Each object is loaded with The class this PR was filed against is the message-less That also refines the last bullet above. These objects do not go on to stop in The change still stands on its own terms — pyelftools reporting a missing dynamic string table with a bare |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_731 |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
An ELF whose
.dynamicsection hassh_link0 has no dynamic string table, and pyelftools reports that with a bareassertrather than anELFError. The message-lessAssertionErrorescapedMetaELF.extract_soname(), killingLoader.find_object()and any load that ran the identity heuristic;_get_relro()failed the same way a moment later.Both are best-effort heuristics with a defined "cannot tell" answer, so they now give it, and
extract_soname()asksiter_tags()forDT_SONAMEalone so an object with no soname never needs a string table. Such an object still will not load, sinceELF.__register_dyn()genuinely needs the strings, but it now fails on its real problem.The regression builds its inputs by zeroing that one header field in copies of binaries already in
angr/binaries.Validation: #731 (comment)