# Orphan-code sweep — code that was invisible to every prior scan ## Why this was run `hdcp_subcmd17` was found late, by accident. It had been invisible to every scan in this project because `sub_402910` reaches it via `JUMPOUT`, so IDA never made it a function -- and every tool I used (bug scans, the 54 `handlers/*.c` files, the xref maps) iterates over *functions*. Code that is not in a function does not exist to any of them. That is a systematic blind spot, not a one-off. This sweep enumerates it: for each binary, compute the set of bytes not covered by any defined function, drop padding/literal pools, and keep regions that contain real instructions or have inbound CALL/JMP xrefs. ## Result: 10 functions were missing across 2 binaries ### HDCP (105 -> 108 functions) | addr | frame | callers | verdict | |---|---|---|---| | `hdcp_orphan_403500` | 0x54 | `0x402f0c`, `0x40419c` | clean | | `hdcp_orphan_403EB0` | 0x29C (668 B) | `0x4036d8` | clean | | `hdcp_orphan_404118` | 0x438 (1080 B) | `0x402428` | clean | `hdcp_orphan_403500` looked dangerous: if ( a6 >= 0x40 ) { ta_memcpy(a4, dst, 0x40u); *a5 = 64; } // writes 64 bytes A 64-byte write whose only guard is a caller-supplied length. Both call sites pass `a6 = 0x20`, so the branch is never taken and the write never happens. Bounded -- but it is exactly the shape that would be a bug if any caller passed >= 0x40. `hdcp_orphan_404118` requires `a2 == 522` and copies 522 bytes into a 528-byte buffer. Fits. `hdcp_orphan_403EB0` copies a constant 0x93 into a 152-byte slot. Fits. (Hex-Rays renders that slot as `v10[16]`; as usual the declared size is wrong -- the real gap to the next variable is 152 bytes. Do not trust it.) ### ASD (1553 -> 1560 functions) `asd_orphan_D0974C`, `D0C0A0`, `D10F70`, `D135C4`, `D17DFC`, `D17EB4`, `D17FFC`. None contains a variable-size copy. `asd_orphan_D135C4` is the interesting one: it is called from `0xd13538`, i.e. **inside the verification chain that gates the ASD 0x308 OOB copy**. It is an ASIC/firmware gate: SVC 0x8D -> id in R0, must be <= 0x14 TST (1 << id), #0x10000C -> id must be 2, 3 or 20 then version checks on the returned dword It does not open the 0x308 gate by itself, but it is a previously-unseen precondition on that path and it was absent from `ASD-REACHABLE-AUDIT.md`. ## CORRECTION: `hdcp_verify_mac` was three functions merged The sweep exposed a real error in my annotations. The saved IDB had: hdcp_verify_mac = 0x403FF4 - 0x40423C Inside that range IDA was using **two different frame bases** -- `[SP,#0x44+..]` at `0x4040fc` but `[SP,#0x42C+..]` at `0x404216` -- and the prologue pushes `{R4-R11,LR}` while `0x404238` pops `{R4-R8,PC}`. The true layout is: hdcp_verify_mac 0x403FF4 - 0x40410E (282 B) ADDEQ SP,#0x44 ; POPEQ {R4-R11,PC} literal pool 0x404110 - 0x404117 orphan function 0x404118 - 0x40423C PUSH {R4-R8,LR} ; SUB.W SP,#0x438 So my earlier statement that "`hdcp_verify_mac` is 217 instructions and contains no backward branch" was computed over the **wrong range** -- it covered three functions. The conclusion (no loop) survives re-checking on the true 282-byte body, but the measurement that produced it was invalid. ## What this does NOT change The hang analysis is unaffected. The canary check (`0x4040f8`-`0x404106`) and the crypto calls (`0x404086`, `0x4040dc`, `0x4040e4`) are all inside the true `hdcp_verify_mac`, and `ADDEQ SP,SP,#0x44` confirms the 68-byte frame with the canary at `SP+0x40` sitting directly above the 32-byte output buffer at `SP+0x20`. ## Net No new vulnerability. The value is coverage and two corrections: a whole class of code was outside every previous scan, and one load-bearing function boundary was wrong. Both are now fixed in the saved IDBs.