re: the ind_call damage is bounded - no corpus claim was contaminated

The protective sweep after last commit's refutation. The question was which
existing claims the ind_call cross product voids. Answer: none of the ones the
corpus makes.

Every caller-count claim in the corpus verifies against call edges, with zero
ind_call contamination:

  title-crash-stl-tree      sub_82457780  "one caller"     call=1   ind_call=0
  isl-trigger-queue         sub_8226EAB8  "16 callers"     call=16  ind_call=0
  isl-coroutine-spawner     sub_822737C8  "seven callers"  call=7   ind_call=0
  challenge-mission-gate    0x82175110    "22 callers"     call=22  ind_call=0

4 of 4 exact, and not one of the four carries a single ind_call edge.

There is a structural reason for that rather than luck. Partitioning the two
target populations: 1710 targets have ind_call edges, 12170 have call edges, 103
have BOTH, 1607 are ind_call-only, 12067 are call-only. And all 1710 ind_call
targets are vtable entries - 1710 of 1710, zero partials - against a control
where only 273 of the 12170 call targets are. So ind_call fires only on virtual
methods, and 1607 of them have no direct caller at all, which is exactly why the
two EX_ screens came back empty on call and flooded on ind_call.

The residual risk is narrow and nameable: the 103 targets carrying both kinds,
where a caller count taken without a kind filter would be inflated by about 633.
Everywhere else the two populations are disjoint, so a call-based count is safe
and an ind_call-based one is meaningless.

Rule for future work: always filter kind='call'; and when a function has no call
edges, that is a fact about it - it is a virtual method - not a gap to be filled
from ind_call.

All seventeen artefacts byte-identical.
This commit is contained in:
Sylpheed RE agent
2026-08-28 11:24:14 +00:00
parent 6736786b66
commit e23eea36f7
2 changed files with 68 additions and 0 deletions

View File

@@ -6941,3 +6941,28 @@ a structural difference, not a coincidence.
🔴 **Blocked**: the `+184` writer. Next route with power = the RTTI behind those
two anonymous classes, or a runtime watch — **not** another static offset search.
---
## ✅ 2026-08-28 — the `ind_call` damage is bounded, and no corpus claim was contaminated
Item (a), the protective sweep after last iteration's refutation.
✅ **Every caller-count claim in the corpus verifies against `call`, with zero
`ind_call`**: `sub_82457780` "one caller" → 1; `sub_8226EAB8` "16 callers" → 16;
`sub_822737C8` "seven callers" → 7; `0x82175110` "22 callers" → 22. **4 of 4
exact, 0 `ind_call` edges among them.**
🔑 **And there is a structural reason, not luck.** Targets with `ind_call` edges:
**1 710**; with `call` edges: **12 170**; **both: 103**; `ind_call` only:
**1 607**; `call` only: 12 067. **All 1 710 `ind_call` targets are vtable
entries — 1 710 of 1 710, zero partials** (control: only 273 of the 12 170
`call` targets are). So `ind_call` fires *only* on virtual methods, and 1 607 of
them have no direct caller at all — exactly why the two `EX_` screens were empty
on `call`.
⚠️ **Residual risk, named**: the **103** targets with *both* kinds, where an
unfiltered count would inflate by ~633. Elsewhere the populations are disjoint.
**Rule**: always filter `kind='call'`; and a function with no `call` edges is a
**virtual method**, not a gap to fill from `ind_call`.