{
  "finding_id": "DF-5701",
  "status": "reproduced",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "verdict": "bcmp.c:58 stores the size_t length in an int. Reproduced on the pristine source in the DFly guest at both -O2 and -O0: (A) bcmp(a,b,2^32) returns 0 (equal) having compared zero bytes - the truncation yields len==0 and the early-out at bcmp.c:62-63 fires; (B) bcmp(a,b,2^32+8) returns 0 (equal) comparing only the first 8 bytes while the buffers differ at byte 8; (C) bcmp(a,b,2^31) takes len=INT_MIN into `len -= sizeof(long)` at bcmp.c:88/114, the signed overflow wraps the counter positive, and the function walks forward past both buffers comparing garbage until it faults (SIGSEGV on a guard page in the rig; a kernel would take an unmapped-page panic). In any equality/security use, (A)/(B) are a false-equal bypass primitive and (C) an unbounded read scan. Impact is none on DragonFlyBSD because the file is dead code: sys/conf/files:2195-2237 omits it, pc64/conf/files:131 builds x86_64/bcmp.s (full 64-bit %rdx length, disasm in pack), vkernel links libc. The bug is FreeBSD-heritage code designed for 32-bit size_t and goes latent-lethal the moment any platform config re-adds the file.",
  "exploit_chain": "",
  "evidence": "logs/trunc2.out (-O2: FALSE EQUAL at 2^32, FALSE EQUAL at 2^32+8, SIGSEGV unbounded walk at 2^31; RESULT A=1 B=1 C=1); logs/trunc0.out (-O0: identical); logs/truncfix.out (post-fix: FIX-PASS, no false equal - huge lengths genuinely compare and fault on the guard as memcmp would); logs/kernel_bcmp_disasm.txt (shipped kernel bcmp = asm version, no truncation)",
  "kernel_refs": [
    "sys/libkern/bcmp.c:58",
    "sys/libkern/bcmp.c:62-63",
    "sys/libkern/bcmp.c:88",
    "sys/libkern/bcmp.c:110-111",
    "sys/libkern/bcmp.c:114",
    "sys/libkern/bcmp.c:128-129",
    "sys/libkern/bcmp.c:142",
    "sys/conf/files:2195-2237",
    "sys/platform/pc64/conf/files:131"
  ],
  "poc_changes": "Seed sketch had no compiler on the host; moved to the DFly guest (cc 8.3). First harness version crashed in its own memset (it filled a 4096-byte page starting 64 bytes in) - a rig bug found by the rig itself, fixed by giving each buffer its own guarded arena. Case (C) initially survived because case (B) had flipped a byte the walk then mismatched on; restored the byte so (C) demonstrates the true unbounded walk. Added the -O0 build to pin the truncation behavior across optimization levels.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 180,
  "guest_dirty": 0,
  "build_cmd": "cd findings/poc/DF-5701 && ./build.sh",
  "run_cmd": "cd findings/poc/DF-5701 && ./run.sh",
  "code_hash": "b936ffa477d986cb1603f2fefc55519dd8ae7b0cc626c3277f15c91078302695",
  "notes": "This is the only way the DF-5676 class could get worse from bcmp.c: a >=2^31 length converts a page-contained over-read into an unbounded forward scan - equally unreachable today (dead file). The BE fallbacks `return(length)` at bcmp.c:142 truncates size_t to int too; subsumed here since the whole length pipeline is replaced by fix.diff. Guest left running, untouched beyond /tmp scratch (cleaned).",
  "recommended_fix": "Make the counter size_t with explicit `len >= sizeof(long)` loop conditions and a bytewise tail (fix.diff, shared with DF-5700).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff validated at rig level on the guest: post-fix, lengths 2^32 and 2^32+8 no longer return a false equal - bcmp genuinely attempts the full comparison (SIGSEGV on the guard page of the 3-page arena, exactly as memcmp would), and the 2.3M-case differential stays at 0 failures. Kernel rebuild validation not applicable: the file is in no DFly kernel build.",
  "fix_evidence": "logs/truncfix.out (RESULT: FIX-PASS (no false equal)), logs/fixed.out in the DF-5700 pack (differential 0 failures post-fix), fix.diff"
}