Skip to content

Fix Clemory backer removal and the BackedCGC backend - #718

Open
zardus wants to merge 1 commit into
masterfrom
feature/backedcgc
Open

Fix Clemory backer removal and the BackedCGC backend#718
zardus wants to merge 1 commit into
masterfrom
feature/backedcgc

Conversation

@zardus

@zardus zardus commented Aug 9, 2026

Copy link
Copy Markdown
Member

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

Loading anything with the backedcgc backend failed with "Can't find backer to remove". Clemory.remove_backer() bisected right, landing one index past the backer it was asked to drop, so no removal ever found its target; split_backer() and add_backer(overwrite=True) were unusable for the same reason.

Behind it the backend has its own defects: it mixes linked and object-relative addresses, mutates the backer list while iterating it, assigns to Region's read-only permission properties, and returns None from thread_registers() where Backend documents a mapping. Both backers are now the optional mappings the docstring already describes.

The regression loads binaries/tests/i386/patchrex/memory_scanner with and without a process dump.

Validation: #718 (comment).

sync: angr/angr#6795

Loading anything with the backedcgc backend raised "Can't find backer to
remove". Clemory.remove_backer() searched with bisect_right, which always
lands one index past the backer whose start matches, so no removal ever
found its target and BackedCGC.__init__ died on the first file backer it
tried to drop. split_backer(), and add_backer(overwrite=True) through it,
were broken the same way.

The backend had further defects on that path:

- It compared segment vaddrs and the caller's memory_backer keys, which are
  linked addresses, against the object's memory, which is keyed relative to
  the object's base. It dropped the executable segment it meant to keep and
  mapped the dump at the wrong addresses.
- It iterated the backer list while removing from it, so every backer
  following a removed one was skipped.
- FakeSegment assigned to is_readable, is_writable and is_executable, which
  are read-only properties on Region, so any non-empty memory_backer raised
  AttributeError before a byte of it was mapped.
- Both backers are documented as optional, but a missing memory_backer
  raised AttributeError, and thread_registers() returned None where Backend
  documents a mapping and angr's SimOS calls .items() on the result. Both
  are empty mappings now when the caller supplies nothing.

Removing a Clemory's last backer now happens for real, so _update_min_max()
restores the empty state a fresh Clemory has instead of asserting;
split_backer() passes through that state on every split.
@zardus

zardus commented Aug 9, 2026

Copy link
Copy Markdown
Member Author

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

Validation record for head 9fc044143b73ef5f83cae77a6476d01193bd7dea against baseline b58ea02a446106647cdaae32bdf91b7062404cc1, with fixtures from angr/binaries 9a8974a63422e155e4af54edceebd099e19aad64.

  • Regression: python -m pytest -q tests/test_backedcgc.py tests/test_clemory.py — on the baseline the two BackedCGC tests and test_remove_backer, test_split_backer, test_add_backer_overwrite fail with ValueError: Can't find backer to remove; on head all 8 pass
  • Focused: python -m pytest -q tests/test_backedcgc.py tests/test_clemory.py — 8 passed
  • Full suite: python -m pytest -q — 207 passed, 9 skipped
  • Consumer: python -m pytest -q tests/simos/test_backedcgc.py in SimCGC: Keep the CGC defaults when a dump omits its optional backers. angr#6795 — 4 fail against this baseline, 4 pass against this head
  • Lint: pylint 4.0.6 with the angr CI pylintrc — cle/backends/cgc/backedcgc.py, cle/memory.py and tests/test_backedcgc.py at 10.00/10, tests/test_clemory.py 5.00 to 6.40
  • Types: pyright 1.1.411 — cle/backends/cgc/backedcgc.py 5 errors to 0, cle/memory.py and tests/test_backedcgc.py clean, tests/test_clemory.py badness 0.714 to 0.682
  • Pre-commit: pre-commit run --all-files — every hook passes and leaves the tree unchanged
  • Ecosystem: cle and angr built from source together — cle 207 passed/9 skipped, angr 2475 passed/46 skipped/2 xfailed/260 subtests, cargo test --release 35 passed
  • Loader non-regression: 177 binaries from binaries/tests loaded on baseline and head — identical backer starts, sizes, min/max, consecutiveness and byte content for every object, and the same 10 unsupported formats rejected on both

Caveats: the backend still marks dump-only regions non-executable, as it always intended to; a CGC replay that needs an executable stack passes permissions_map, which angr's SimCGC.state_entry prefers. The local run resolved pyvex and claripy at 9.3.1.dev0.

@angr-bot

angr-bot commented Aug 9, 2026

Copy link
Copy Markdown
Member

Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_718

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants