SSA and dephication rewriting engines drop vector_count and vector_size when rebuilding a BinaryOp
- Linguagem predominante
- Python
- Estrelas
- 9.1k
- Forks
- 1.2k
- Merge médio
- 16h 20min
- PRs com merge (30d)
- 169
Descrição
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
### Description
The SSA and dephication rewriting engines rebuild an AIL `BinaryOp` when one of its
operands is rewritten, and neither passes `vector_count` or `vector_size`.
`angr/analyses/decompiler/ssailification/rewriting_engine.py`, lines 423-441 at
`0e18fa25e`:
```python
def _handle_expr_BinaryOp(self, expr: BinaryOp) -> BinaryOp | None:
new_op0 = self._expr(expr.operands[0])
new_op1 = self._expr(expr.operands[1])
if new_op0 is not None or new_op1 is not None:
return BinaryOp(
expr.idx,
expr.op,
[
expr.operands[0] if new_op0 is None else new_op0,
expr.operands[1] if new_op1 is None else new_op1,
],
expr.signed,
bits=expr.bits,
floating_point=expr.floating_point,
rounding_mode=expr.rounding_mode,
**expr.tags,
)
return None
```
`angr/analyses/decompiler/dephication/rewriting_engine.py`, lines 350-368, is the same
code.
`BinaryOp.__new__` defaults both to `None` (`angr/ailment/expression.py`, lines 323-324),
so the metadata is not preserved but silently replaced:
```
original : bits 128 vector_size 8 vector_count 16
after rebuild : bits 128 vector_size None vector_count None
```
(constructing an `InterleaveLOV` over two 128-bit registers and passing it through the
rebuild above verbatim).
`bits` is passed and does survive. Only the vector shape is lost.
### Consequence
**This does not affect #6988.** Every `_handle_binop_default` that PR introduces or
renames reads `expr.bits` and nothing else, so an operator routed to a default is
unaffected by the loss.
It matters for the first handler that models a vector operator's real semantics, which is
the natural follow-up once operators like `CatEvenLanesV` reach the engines. The concrete
consequence is already in the tree: `SimEngineAILSimState._handle_binop_InterleaveLOV`
(`angr/engines/ail/engine_light.py`, line 895) opens with
```python
assert expr.vector_size is not None
assert expr.vector_count is not None
```
and computes lane slices from both. A handler written on that shape works pre-SSA and
asserts post-SSA, and the failure will look like a bug in the new handler rather than in
the rewrite.
`SimplifierAILEngine._handle_binop_default`
(`angr/analyses/decompiler/optimization_passes/engine_base.py`, lines 397-409) is the
model that gets it right — it rebuilds with the same argument list plus:
```python
vector_count=expr.vector_count,
vector_size=expr.vector_size,
```
### How this was established
By reading the three rebuild sites, then constructing a `BinaryOp("InterleaveLOV", ...,
bits=128, vector_count=16, vector_size=8)` and passing it through the rewriting engines'
argument list verbatim, which returns `vector_size=None, vector_count=None`. No
decompilation is needed to show it, and I am not claiming an observed wrong result today —
no in-tree handler reads the metadata after this point.
### Duplicate search performed
Diff level, not title. `gh pr list -R angr/angr --state all` over the recent range, with
every candidate touching `ssailification/`, `dephication/` or AIL expression construction
grepped for `vector_count`, `vector_size` and `_handle_expr_BinaryOp`. `git log --all -S`
on the literal `vector_count=expr.vector_count` matches only the simplifier engine's
existing use. No open or closed issue mentions vector metadata loss across a rewrite, and
the sibling worktrees under `features/` all carry both rebuild sites unchanged.
### Suggested fix
Add the two arguments at both sites, matching the simplifier.
### Context
Found while investigating the `KeyError` class that #6988 closes: the AIL binop dispatch
had no entry for the NEON lane operators `CatEvenLanesV`, `CatOddLanesV` and `GetElemV`,
which over a local decompilation sweep measured at 2026-08-28 14:41:17 UTC accounted for
168 distinct functions decompiling to an empty body across 162 distinct objects. (Each
failing function records the `KeyError` twice, so counting error occurrences rather than
functions doubles that figure.) Asking whether those operators could be given real lane
semantics rather than an opaque result is what surfaced this.
session: crazybins
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Avaliação
Esta issue ainda não foi avaliada.