# DF-3956 VERDICT

**Verdict: INCONCLUSIVE at kernel level (no AMD GPU) — source-certain u32
underflow wild read at +0x3FFFFFFFC (~16 GiB); the verbatim consumer
expression faults in the userland simulation exactly as predicted.**

## Trace

1. **Producer can legitimately produce num_entries == 0.**
   sumo_construct_vid_mapping_table (sumo_dpm.c:1616-1645): entries are only
   written for `table[i].ulSupportedSCLK != 0`; the compaction loop then
   breaks with `i == 0` when `entries[0].vid_7bit == 0` (empty table). Also,
   kv_parse_sys_info_table (kv_dpm.c:2495-2546) treats a *missing*
   IntegratedSystemInfo table as success (`return 0` outside the
   `atom_parse_data_header` guard), leaving the whole kzalloc'd
   `pi->sys_info.vid_mapping_table` zeroed — num_entries == 0 without any
   crafted sAvail_SCLK at all.

2. **Consumer underflow (this file).** kv_convert_vid2_to_vid7
   (kv_dpm.c:548-568) and kv_convert_vid7_to_vid2 (:570-592) only touch
   vid_mapping_table when `vddc_sclk_table->count == 0` (the else-branch) —
   true on KB/ML boards whose VBIOS lacks the sclk voltage-dependency table.
   With num_entries == 0 the match loop runs zero iterations and falls through
   to `entries[num_entries - 1]`: num_entries is `u32`
   (sumo_dpm.h:64-67) → 0xFFFFFFFF, entry size 4 → displacement
   0xFFFFFFFF × 4 = **0x3FFFFFFFC ≈ 16 GiB** past the kv_power_info object.

3. **Boot-time call-in.** kv_dpm_enable → kv_init_graphics_levels else-branch
   (kv_dpm.c:2370-2386): kv_set_vid (:2382 → :612-621 →
   kv_convert_2bit_index_to_voltage :604 → :566) and the high-voltage break
   check (:2378). Earlier still: kv_dpm_init → kv_parse_sys_info_table →
   kv_construct_max_power_limits_table (:2543 → :1973) and
   kv_get_high_voltage_limit (:2122). All boot-time on the target APU with the
   crafted/empty VBIOS.

## Harness

Replicates the producer's num_entries computation (0 on the all-zero
sAvail_SCLK list), the consumer's verbatim `entries[num_entries - 1].vid_7bit`
expression, and the struct layout (`_Static_assert(entry==4)`). Crash mode
places the table against a guard page: child SIGSEGV sig=11; analysis prints
`entries[0xffffffff] -> +0x3fffffffc (16.00 GiB)`.

## Why Low

Wild *load* (a 16-bit vid value) feeding voltage math; no write, no leak
channel; trigger needs KV-family APU + VBIOS with both the sclk dependency
table absent and the vid mapping empty/missing. Precedent: amdgpu twin DF-3890
(Low). (The sibling DF-1437 in sumo_dpm.c covers the OOB *write* inside the
producer — different file, different primitive, already filed.)

## Fix validation

fix.diff adds `num_entries == 0` guards returning 0 in both converters
(in-file fix; a producer-side clamp in sumo_dpm.c would also work but is that
file's scope). Not built on the guest (no AMD GPU): `fix_status:
not_testable`. Guards are trivially sufficient by inspection.

## 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.
