Load static archives with a /SYM64/ symbol table - #736
Conversation
GNU ar names the archive symbol table "/" for the 32-bit index and "/SYM64/" for the 64-bit one, which it writes for mips64 targets and for archives too large to index with 32-bit offsets. arpy only recognizes the first spelling: it classifies "/SYM64/" as a member whose real name lives in the long filename table and then raises ValueError parsing "SYM64" as the offset into that table, so no such archive loads at all. arpy discards the symbol table for either spelling, so skip a leading 64-bit one instead of handing it to arpy, and only when its header fits inside the file. Wrap arpy's parse failures in CLEInvalidBinaryError as well, so they no longer escape cle.Loader as a bare ValueError or an arpy exception.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
The regression loads The failure came out of a sweep of real-world static archives run on cle Inputs probed by hand beyond the regression: even- and odd-length symbol tables, an empty index, a size field padded with spaces, a negative size, a non-numeric size, a size running past the end of the file, a Caveats: the first Windows CI attempt failed before collecting anything, when two pytest-xdist workers raced to install the pyvex FFI parser cache and |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_736 |
The first version of this test assembled its own ar archives with struct.pack. That is a test input committed to the wrong repository in a form review does not notice, and a hand-assembled container has a shape no toolchain emits, so it can pass while the real format still fails. Load fixtures instead: - tests/mips64/sym64_archive.a, new in angr/binaries: a 3,104-byte MIPS64 big-endian static library, from a public OS distribution, whose index is a "/SYM64/" symbol table. - tests_src/.../libmbed.a, already in angr/binaries: an ARM library with an ordinary "/" symbol table and a "//" long filename table, covering the case that has to keep working. It needs rebase_granularity to dodge an unrelated R_ARM_THM_CALL range failure, which is what cle's error message for that failure asks for. The two malformed inputs are copies of those fixtures with one member header field overwritten -- the terminating magic, and the symbol table size -- so each differs from a real archive only in the field under test. Drop test_bad_long_name_offset. It invented a "/nope" member to reach the same int() failure a "/SYM64/" header reaches for real, and test_sym64_size_past_end now covers that path with the real spelling.
06f2f87 to
1ffb9f1
Compare
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
cle.Loadercannot open a static archive whose index is the 64-bit variant. GNU ar names that member/SYM64/; arpy classifies it as a member whose real name lives in the long filename table and then raises a bareValueErrorparsingSYM64as the offset into that table. Every mips64 archive is written this way, as is any archive too large to index with 32-bit offsets.arpy discards the symbol table for either spelling, so the AR backend now skips a leading
/SYM64/member itself, and only when the member header fits inside the file. It also wraps arpy's parse failures inCLEInvalidBinaryError. The classification really belongs in arpy, but both the pinned 1.1.1 and the current release get it wrong.The regression loads a real mips64
/SYM64/library added by angr/binaries#176, so the checks here stay red until that merges.Validation: #736 (comment)