# DF-5756 — VERDICT

**Status: reproduced** (`certain`). Fix authored and **validated** at the
converter level (`fix_status: fixed`).

## Reproduced manifestations (baseline)

| evidence | file:line | observation |
|---|---|---|
| CESU-8 emission | `sys/libiconv/iconv_ucs.c:255` (only `0xd8` prefix checked) → `:264-266` (lone low surrogate as plain char) → `:293-312` (no surrogate check) → `ucs4_to_utf8` `:495-497` (`w=3`) | witness: `"\xDC\x00"` → `ret=0 out=ed b0 80` |
| asymmetry | same | witness: `"\xD8\x3D"` → `ret=-1` (high surrogate alone correctly rejected) |
| crafted-image e2e | `msdosfs_conv.c:946` (`win2unixchr` → `convchr(pm_w2u)`, 2-byte out) | dirent `abcd?fghij.k` — silent `?` for invalid Unicode; `?xyzabcd.k` for lone high |
| userland contrast | `logs/difftest.log` | `iconv(3)` UTF-16BE→UTF-8 `"\xDC\x00"` → EILSEQ |

## Honest scope

The 3-byte CESU-8 bytes themselves do not escape through msdosfs (the
per-character staging buffer is 2 bytes, so the emission fails the
`dstlen < w` check at `iconv_ucs.c:505-506` and msdosfs substitutes `?`).
They **do** escape through any consumer with a ≥3-byte output buffer
calling the same kernel converter — proven in-kernel by `cesu_witness.ko`
via the exported `iconv_open`/`iconv_convchr` API. The msdosfs-visible
defect is the **silent acceptance** (no EILSEQ-equivalent) of unpaired
surrogates. Severity Low: invalid-Unicode laundering / parser-confusion
input, no memory corruption, no info leak.

## Fix validation (fix.diff: leading-DC rejection at the input stage +
surrogate check before UTF-8 emission)

Applied stacked with DF-5755's fix; `libiconv.ko` rebuilt (`-Werror`
clean), reloaded before `msdos_iconv.ko`:

| trigger | baseline | patched |
|---|---|---|
| witness `lowsur "\xDC\x00"` | `ret=0 out=ed b0 80` | **`ret=-1`, out untouched** |
| witness `highsur-lone` | `ret=-1` | `ret=-1` (unchanged) |
| witness `valid-pair D8 3D DE 48` | `f0 9f 99 88` | **identical** (no regression) |
| msdosfs readdir (crafted image) | `abcd?fghij.k` | `abcd?fghij.k` — unchanged by design: `win2unixchr` renders both accept-then-fail and reject-at-input as `?`; the delta is the converter now *rejects* invalid Unicode (`ret=-1`) instead of laundering it into CESU-8 when given room |

`fix_status: fixed` (converter-level behavior delta decisive via witness;
no regression on valid pairs).

## PoC notes

* `craft5756.c` initially searched for the full UTF-16LE name across the
  LFN entry — LFN entries split names at wePart1/wePart2 with 3 metadata
  bytes between, so the search was fixed to per-part patterns with an
  attr==0x0f cross-check.
* PoC fixes vs seed: none applicable (authored fresh); msdosfs mount
  `dirmask` and DF `dirent` (`_DIRENT_DIRSIZ`) quirks as in DF-5755.

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