Probe UEFI compatibility without assuming a file object - #720
Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
Head Inputs, both added by angr/binaries#176: Caveats: the two assertions on |
01afdc9 to
ee7855f
Compare
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_720 |
The loader promises a backend only that a stream supports read and seek, but UefiFirmware._to_bytes called fileno() on it and caught only the io.UnsupportedOperation an io.IOBase would raise. Backend detection offers every stream to every default backend, so a stream that is not a file object aborted detection with an AttributeError instead of the probe returning False. The stream arpy hands out for a static archive member is one: a BSD-flavored archive puts its __.SYMDEF symbol index in the member list, no backend claims it, and the load of the whole archive failed there. Catch that too, and take the mmap shortcut only when the stream spans the file behind the descriptor. mmap maps that whole file from offset 0, which is not what an archive member sharing its container's descriptor holds. An empty file skips the shortcut as well, where mmap used to raise ValueError. Return bytes rather than a memoryview for a BytesIO, which is what the CARTFile backend re-enters the loader with. uefi_firmware joins a compressed section's preamble to its body before decompressing it, and a memoryview cannot be joined to anything. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ee7855f to
2369d83
Compare
The test assembled its own firmware volume and BSD-flavored archive with struct.pack, which pins the loader to a shape no toolchain emits and passes while the real formats still fail. Load Debian's edk2 build of ArmVirtQemu and a BSD static archive whose first member is a __.SYMDEF symbol index, both from angr/binaries. The volume holds its 93 AArch64 PE drivers behind an LZMA-compressed section, so asserting that the loader reports them as child objects says the volume was parsed rather than only recognized, which is what _to_bytes returning a concatenable object buys. The archive's symbol index is the member arpy hands out that has no fileno, and its second member gives _to_bytes a stream that shares a descriptor with a larger file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The name a firmware volume gives a driver lives on UefiModuleMixin, not on Backend, so reading it straight off child_objects fails the Typecheck job. Every child a volume produces is built as a UefiPE or a UefiTE, so assert that and read the name through the narrowed type. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Loading a BSD-flavored static archive fails with
AttributeError: 'ArchiveFileData' object has no attribute 'fileno'. Detection offers every stream to every default backend, and the loader promises a backend only read and seek, butUefiFirmware._to_bytescallsfileno()and catches only theio.UnsupportedOperationanio.IOBasewould raise.The probe has to answer for such a stream, so it now reads it instead, taking the mmap shortcut only when the stream spans the file behind the descriptor. It also returns bytes rather than a memoryview for a
BytesIO— firmware unpacked by the CARTFile backend arrives that way, anduefi_firmwarejoins a compressed section's preamble to its body before decompressing it.The regression test loads a real firmware volume and a real BSD archive, both fixtures added by angr/binaries#176, so the checks here stay red until that merges. Such an archive still does not load afterwards, because its symbol index is handed to the loader as if it were an object file; and #716 registers
STM32Backend, whoseis_compatiblecallstell()and will need the same treatment.Validation: #720 (comment)