# DF-4683 — ar2317: FillVpdTable/interpolate span never clamped → OOB heap WRITE
past ar2317State (uint16 wrap runaway + valid-oversized-span variants)

NEW (not covered by the ar5413/ar2316/ar2417/ar2413 family twins): neither
`ar2317FillVpdTable()` nor the interpolate loop bounds the pd-gain power span
to the vpdTable row width (`MAX_PWR_RANGE_IN_HALF_DB = 64`,
ah_eeprom_v3.h:291) or validates `Pmax >= Pmin`.

## Build

Same harness as DF-4680: `cd /root/df2317 && sh build.sh`
(the ar2317State object is placed with its end exactly at a page boundary and
a PROT_NONE guard page after it, emulating the kernel heap allocation)

## Run

```
./ar2317_harness 4     # descending EEPROM curve  -> uint16 wrap runaway
./ar2317_harness 5     # valid curve spanning 102 -> plain missing clamp
```

## Expected (baseline)

```
--- mode 4 ---
REPRODUCED: SIGSEGV si_addr=0x800476000
  object guard page at 0x800476000 (struct end); si_addr is 2008 bytes past
  struct start (sizeof=2008)
  FillVpdTable loop bound (uint16_t)(Pmax-Pmin) = (uint16_t)(84-90) = 65530
  entries (131060 bytes) into a 64-wide row
MATCH: unbounded OOB WRITE ran off the end of the ar2317State heap object

--- mode 5 ---  (identical guard-page fault, from VALID data, no wrap)
```

- **Mode 4**: `Pmin_t2/Pmax_t2` are computed at ar2317.c:372-382 without any
  monotonicity check; a descending pwr_t4 list gives `Pmax < Pmin`, so
  `while (ii <= (uint16_t)(Pmax - Pmin))` (ar2317.c:289) wraps to ~65530 and
  the loop writes up to **131060 bytes** from `vpdTable_L[0][0]` — through
  the whole 2008-byte object and off its end (kernel: adjacent heap objects
  corrupted / panic).
- **Mode 5**: a valid ascending curve spanning 102 half-dB needs no wrap:
  FillVpdTable writes row 3 indices 64..102 (intra-object spill) and the
  interpolate loop (ar2317.c:393-398) writes `VpdTable_I[3][0..101]` —
  vpdTable_I is the **last** member, so indices ≥64 land past the object.

Written values are EEPROM-Vpd-derived (0..255, or 0xFFxx on negative
extrapolation): semi-controlled kernel-heap overwrite. Rated **Medium** (the
twins are Low) for the beyond-object write reach.

## Fix validation

`fix.diff` (fixD) skips any pdGain with `Pmax < Pmin` or span ≥
`MAX_PWR_RANGE_IN_HALF_DB` (`continue` before the FillVpdTable/interpolate
calls). Patched: mode 5 completes with fixD alone (numPdGainsUsed=3); mode 4
completes with fixD+fixB (`fixB.diff` = DF-4681's early return; skipping the
inverted gain leaves zero gains, whose residual path DF-4681's fix covers).

**The same defect exists verbatim in ar2413.c:309, ar2316.c:312,
ar5413.c:353, ar2425.c:311 — recommend fixing all five together.**
