Skip to content

Survive a CIE that declares no FDE encoding - #768

Open
zardus wants to merge 1 commit into
masterfrom
feature/fde-missing-encoding
Open

Survive a CIE that declares no FDE encoding#768
zardus wants to merge 1 commit into
masterfrom
feature/fde-missing-encoding

Conversation

@zardus

@zardus zardus commented Aug 19, 2026

Copy link
Copy Markdown
Member

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

The R augmentation that gives a CIE its FDE encoding is optional, but pyelftools reads it unconditionally — cie.augmentation_dict['FDE_encoding'] in callframe.py — and raises KeyError when it is absent instead of falling back to the default pointer encoding.

ELF._load_function_hints_from_fde catches DWARFError and ValueError, so that KeyError escaped it and failed the entire load whenever debug information was requested. An object whose unwind tables happen to be unreadable became an object that cannot be loaded at all:

cle.Loader("angr/binaries/tests/mips/busybox", auto_load_libs=False, load_debug_info=True)
# KeyError: 'FDE_encoding'

Catching it alongside the others, and keeping the existing warning, restores the behaviour the handler was already written for. The unwind hints for such an object are lost either way; the load no longer is. The same handler guards _load_exception_handling, so both are widened.

tests/mips/busybox and tests/mipsel/busybox both carry such a CIE, so the regression loads them with load_debug_info=True and needs no new fixture.

The underlying bug is pyelftools', not this project's — a CIE without R should yield DW_EH_PE_absptr rather than raising — so this is resilience against a dependency rather than a fix for the root cause.

Validation: see the comment below.

The "R" augmentation that gives a CIE its FDE encoding is optional, but
pyelftools reads it unconditionally and raises KeyError when it is absent
rather than falling back to the default pointer encoding. The FDE reader here
catches DWARFError and ValueError, so that KeyError escaped and failed the whole
load whenever debug information was requested -- an object whose unwind tables
cannot be read became an object that cannot be loaded.

Catch it alongside the others and keep the existing warning. The unwind hints
for such an object are lost either way; the load no longer is.

tests/mips/busybox and tests/mipsel/busybox both have such a CIE, so the
regression loads them with load_debug_info=True.
@zardus

zardus commented Aug 19, 2026

Copy link
Copy Markdown
Member Author

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

Validation record for head 0157f4ab0ded51f944798cebb0b5fb4b6e4705a5 against baseline 5125f1ba0618ab8f6f8ce7fb2322fd949d857a4a.

  • Reproducer: cle.Loader("tests/mips/busybox", auto_load_libs=False, load_debug_info=True) raises KeyError: 'FDE_encoding' from elftools/dwarf/callframe.py:431 on the baseline and loads on the head. tests/mipsel/busybox behaves identically. Without load_debug_info neither raises, because the FDE reader is never reached
  • Regression: pytest tests/test_dwarf_resiliency.py — 2 passed on the head; on the baseline test_fde_without_encoding_augmentation fails with that KeyError, so it depends on the production change
  • Suite: pytest tests — 238 passed, 9 skipped
  • Hooks: pre-commit run --all-files — every hook passes and leaves the tree unchanged
  • Type check: pyright on cle/backends/elf/elf.py reports the same 46 diagnostics on the baseline and on the head, so this adds none; tests/test_dwarf_resiliency.py reports 0
  • Scope: the change widens two except tuples and adds no branch, so it can only affect an object that previously raised. Objects whose FDEs parse are untouched
  • Corpus: a sweep's evidence reader failed on 298 objects, of which 167 are this KeyError — 166 mips/elf and one x86_64/elf. Scanning the 653 ELFs in angr/binaries that carry DWARF, three reproduce it: tests/mips/busybox, tests/mipsel/busybox and tests/x86_64/ALLSTAR_aces3_xaces3

Caveats: this is resilience against a dependency, not a fix for the cause — a CIE without the R augmentation should yield DW_EH_PE_absptr rather than raising, which is pyelftools' to correct, and until it does the unwind hints for these objects are still lost, only silently now instead of fatally. tests/test_clemory.py::test_cclemory fails in my checkout on this head and on unmodified master alike, with cffi.VerificationError while compiling its test extension; that is a toolchain gap in my environment rather than anything to do with this change, and the hosted CI compiles it. The complete workspace gate has not been run on this head — only the suite named above.

@angr-bot

Copy link
Copy Markdown
Member

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

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