Keep a rebased object out of the null page - #765
Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Regression. Images that still map 0, and why that is correct. On the placement sample, 14 of 198 measured still map address 0: 12 are ELFCore images whose own first segment starts at 0, and the main object's placement never goes through Headline object.
Every block remaining in an invented object is a hook node. Peak RSS falls 12%. The two changes are independently sufficient here and are not additive. A 96-byte Scale. Over the scored sample, 1,966 objects contribute 144,547 blocks decoded inside invented memory, split 922 objects / 53,507 blocks where the invented object sits below the image and 1,044 / 91,040 where it sits above:
Noise floor. CFGFast is not reproducible on every input (angr/angr#6840), so the comparison is over sorted block sets rather than counts, and the stock arm was repeated in a second fresh child wherever it was cheap. Across 508 placement, 260 control and 33 synthetic objects the two stock runs disagreed 0 times. The one control-group difference observed is shown directly to be that nondeterminism rather than an effect of either change. Full local gate. cle: 228 passed, 9 skipped. angr: 2,480 passed, 46 skipped, 2 xfailed, 260 subtests passed. angr Rust: 35 passed. Workspace checks, test-inputs and all pre-commit hooks passed with no rewrite. Lint and type checks, merge-base relative, over the changed files: COFF is excluded from the credit. #761 makes a COFF object's undefined externals into imports, so angr hooks them and stops decoding them; a hooked address is exactly what the CFGFast guard lets through. On COFF the two reach the same end by different routes and are not additive, so the 41 COFF objects among the 4,327 measured are broken out and measured again with cle#761 applied to both sides rather than counted here. Rebase. Rebased onto |
_find_safe_rebase_addr starts its search at address 0 when the architecture is narrower than 32 bits or the main image reaches into the top half of the address space, so the first object the loader places itself gets page zero. That object is normally cle##externs. Page zero is then mapped, readable and executable: a null or uninitialized pointer resolves inside a real object instead of faulting, and on 8- and 16-bit targets it answers the RST, BIOS and direct-page addresses those architectures transfer control to, which are outside the image on purpose. Search the space above the image first, then the space at or above the null page, then the null page itself, so a load with nowhere else to go still works. Only the branch that used to start at 0 changes; on every other target the first candidate is the address the function already returned. check_sparse_elf asserted that the extern and TLS objects land below 0xf800. What it guards is that they stay outside the main object's span, whose memory is one backer from 0xf800 to 0xfff00fff, so anything inside it is unreachable through Loader.memory. They now land above that span rather than below it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bc779ad to
ad49e88
Compare
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_765 |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
_find_safe_rebase_addrstarts its search at address 0 whenever the architecture is narrower than 32 bits or the main image reaches into the top half of the address space. The extern object and the other objects CLE invents then land on the null page, so a null or uninitialized pointer in the target reads as an address inside a real object andfind_object_containing(0)answers with the extern object instead of nothing.Try the space above the image first, then the space at or above the null page, and fall back to the null page only when nothing else fits. Only the branch that used to start at 0 changes; every other placement is byte-identical.
Some images still map 0 afterwards and should: an ELFCore whose own first segment starts at 0 never goes through this function, and a 16-bit blob that runs to the top of its address space has nowhere else to go. That last case is the one the issue names as blocking a fix.
Fixes #745.