# DF-4681 — VERDICT

**Status: REPRODUCED (guest, verbatim-extraction harness, mode 2) · impact:
dos · confidence: certain · fix: fixed (validated)**

## Root cause

`ar2317getGainBoundariesAndPdadcsForPowers()` only increments
`numPdGainsUsed` when a gain has `numVpd > 0` (ar2317.c:366-403). An EEPROM
with `xpd_mask == 0` yields all-zero `numVpd` (shared `SetupRawDataset`,
ah_eeprom_v3.c:656-673), leaving `numPdGainsUsed == 0`, yet the function
continues:

- **:405** `*pMinCalPower = Pmin_t2[0];` — `Pmin_t2[]` was never written:
  uninitialized stack read, value flows into `ah_txPowerIndexOffset`
  (ar2317SetPowerTable:559-562). Observed run-to-run variance in the harness:
  0xd4a0 / 0xd570 / 0xd3c0 / 0xd470.
- **:464-467** `while (ii < MAX_NUM_PDGAINS_PER_CHANNEL)
  pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];` with `ii==0`: `ii` is
  `uint32_t`, so `ii-1` = 0xFFFFFFFF → **read at `gb + 0x1FFFFFFFE` bytes
  (+8.59 GB)** — a wild read, not a 2-byte under-read.
- **:468-471** `while (kk < 128) pPDADCValues[kk] = pPDADCValues[kk-1];` with
  `kk==0` — identical wrap from the pcdacTable base.

`:516`'s `HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3)` is a no-op in
release kernels (`AH_ASSERT` undefined; ah_internal.h:665-676 — the guest
GENERIC is such a build), and the caller (ar2317.c:513-515) never checks the
return value.

## Verification (run.log mode 2)

Direct-map survival emulation: the harness mmaps the two exact wild pages
(`gb+0x1FFFFFFFE`, `pcdacTable+0x1FFFFFFFE`), seeds 0x5A5A, and the call
**completes**, with both wild values propagating into hardware-facing
outputs (`gainBoundaries[0]` → AR_PHY_TPCRG5 at :575-580; `pcdacTable[0]` →
32 PHY register writes at :566-573). The complementary fault case (same wrap
arithmetic, unmapped target) is proven by mode 3/DF-4682's SIGSEGV at the
predicted wild address. In-kernel: direct-map garbage (radio misprogrammed
from wild-read values) or KVA-hole panic.

## Fix validation (fix_run.log, fixB section)

`fix.diff`: `if (numPdGainsUsed == 0) return 0;` before the Pmin_t2[0] read,
plus a `numPdGainsUsed < 1 → AH_FALSE` guard in `ar2317SetPowerTable`.
Patched: ret=0, sentinel minPower, gb[0]=0x0000, pcdac[0]=0xaaaa — clean.
`git apply --check` clean; never applied to `sys/`.

## Distinction from known findings

DF-1806 (pass 1) is the numChannels==0 → idxL/idxR wild-read bug: different
trigger (missing piers vs zero gains), different guard. DF-4682 is the same
uint32-underflow class at :445-446 via flat curves — filed separately.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
