Conversation
_meta_imports took the minimum and maximum hint/name RVA over every import and recorded the whole range as one StringBlob. Nothing in the format requires those entries to be contiguous or ordered, so on an image whose imports point at scattered entries the blob covers megabytes of unrelated address space, including code. That reaches angr: CFGFast._process_metadata_regions marks every region cle reports as data, so where the blob covers an address the lift distance is 0, _lift raises SimTranslationError and the address is refused. On tests/x86_64/windows/Project1.vmp.exe the blob is 2,057,692 bytes and covers the entry at 0x706467; on tests/x86_64/windows/7107ab06...bd5 it is 14,995,404 bytes and covers the entry at 0x142a401b4. Collect each entry's own extent instead and coalesce the ones that touch, in the same shape as the region merging in ihex and srec. A normal contiguous hint/name table still comes out as one region. Over the 106 PE files angr/binaries tracks, 62 change and 44 do not, no region of another sort moves, and no byte is covered afterwards that was not covered before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head Measured against angr
The before/after at the entry point of the two reproducers is in the output comment on this pull request, not here. Regression control over all 106 PE files angr/binaries tracks, dumping every meta region on both revisions and diffing them:
Caveats: an unbounded |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS What The run is Before — the import hint/name blob covers the entry, cle master 0e77adeAfter — no metadata region covers the entry, with this change"Flattened meta regions" is what |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_834 |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Why They are not caused by this change. Both shards fail angr's tests, which cle's CI also runs, and the same 21 tests fail on angr master with none of this change present: run 34216086807 on The cause is that those two merged while their archinfo counterpart, angr/archinfo#384, had not. As of this writing #384 is open. libVEX now emits AVX-512 guest state that archinfo's amd64 register file does not describe, so the AVX-512 tests raise This pull request's run is simply the first cle CI run to start after that merge. The merge landed at 10:30Z, this run started at 12:56Z, and no cle run started in between; the previous cle run, at 10:05Z, predates the merge and was green. Re-running these two checks once angr/archinfo#384 has landed should clear them. The change in this pull request is confined to |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
Two PE files
angr/binariesalready tracks have their entry point covered by acle metadata region, so
CFGFasttreats the entry as data and decodes nothingthere. The entry sits in an executable section in both cases:
Every address inside such a region is refused the same way, so on an image where
the region covers the code the analysis can come back with nothing at all.
Root cause
PE._meta_importsincle/backends/pe/pe.pykeeps only the lowest and highesthint/name RVA it sees and records the whole range as one region:
Nothing in the PE format requires the
IMAGE_IMPORT_BY_NAMEentries to becontiguous or in order — each ILT and IAT slot points at one independently. On
Project1.vmp.exethe entries themselvestotal 3,360 bytes inside that 2,057,692-byte span, so 99.8% of what cle reports
as an import string table is whatever else happens to lie between the first entry
and the last, including the entry point.
angr's
_flatten_regionsemits the sub-region,CFGFast._process_metadata_regionsoccupies it in
_seg_list, and the lift distance at any covered address is then0, so
_liftraisesSimTranslationErrorand the address is dropped.Fix
Record each hint/name entry's own extent and coalesce the ones that touch, so the
region describes the bytes cle actually parsed. cle owns this: it is the producer,
and a consumer cannot tell a real string table from a span that merely contains
one.
Coalescing runs rather than emitting one blob per import is deliberate: a normal
contiguous table still comes out as a single region, so 37 of the 99 PE files in
angr/binariesthat have an import hint/name table keep exactly the region theyhad. It follows the same shape as the region merging in
cle/backends/ihex.pyand
cle/backends/srec.py, which merge only exactly abutting regions where thisalso merges overlapping ones.
Two other PE producers can also report a region larger than the data it
describes — the load-config sub-tables, built from header fields nothing
validates, and the resource directory's declared
Size— but neither is thistable and each wants its own change with its own reproducer.
Testing
tests/test_pe_meta_regions.py::TestPEScatteredHintNameTable::test_scattered_hint_name_entriesloads
tests/x86_64/windows/Project1.vmp.exeand asserts 179 hint/name regionstotalling 3,360 bytes with none covering
obj.entry. On master it fails withassert 1 == 179and prints the single 2,057,692-byte blob. The rest of cle'ssuite is unaffected.
The checkable effect on angr: running
CFGFastrestricted to the entry's ownneighbourhood,
_seg_listat the entry goes fromstringtocodeon bothfiles and the entry is recovered as a function, where in that same window before
the change neither file produced a function or a node. These are packed
binaries, and an unbounded
CFGFastover either of them was not run tocompletion, so this makes no claim about whole-binary function counts.
Validation: #834 (comment)
session: sharpen