# DF-1401 — trinity_parse_power_table nonClockInfoIndex OOB read (PoC)

## Summary
`trinity_parse_power_table` (`sys/dev/drm/radeon/trinity_dpm.c:1774-1776`)
indexes the non-clock info array with a VBIOS-supplied `nonClockInfoIndex` (u8)
and **no bounds check**, unlike the clock path at `:1786-1790` which IS
guarded. Crafted VBIOS → OOB read. **Read-only primitive** (no write-through)
→ no escalation; ceiling = OOB-info read / wrong DPM settings (DoS).

## Reachability
`radeon` is a loadable module (`radeon.ko`), not in GENERIC, attaching only to
AMD/ATI Radeon GPUs. The QEMU guest has no AMD GPU, so the bug is **not
live-reachable here**. Proven deterministically with a byte-exact harness
replicating `struct _NonClockInfoArray` (`pptable.h:456-464`).

## Build / run
```sh
./build.sh && ./run.sh
```

## Expected output (bug present)
```
nonClockInfoIndex (from VBIOS) = 200
guard present? : NO (contrast clock path at :1789 which checks >= ucNumEntries)
reads entry [200] of a 1-entry array -> OUT OF BOUNDS
OOB READ CONFIRMED: ... reads ~3200 bytes OOB ...
```
On a fixed driver the guard rejects indices `>= ucNumEntries` and returns
`-EINVAL`.

## Fix
Add the missing guard mirroring the clock path: if
`non_clock_array_index >= non_clock_info_array->ucNumEntries`, free
`rdev->pm.dpm.ps`, NULL it, `return -EINVAL` (`fix.diff`). Validated to compile
into a rebuilt `radeon.ko` (`-Werror`, rc=0; `trinity_dpm.o` built).

## Files
- `trinity_nonclock_oob.c` — byte-exact harness.
- `build.sh` / `run.sh` / `run.log` / `env.txt` / `fix.diff` / `VERDICT.md` / `manifest.json`.
