At Black Hat USA 2026, security researcher Chris Domas argued that C compilers can strip bounds checks, memory wipes, and input validation from optimized binaries, and only post optimization testing remains reliable.
A developer can write textbook-secure C and still ship a vulnerable binary, because the CPU executes what the compiler produces, not what the programmer wrote. At Black Hat USA 2026, security researcher Chris Domas argued in a Black Hat interview recorded by David Bombal and sponsored by ThreatLocker that a compiler obeying the C language specification can legally delete the security checks a developer wrote, and ship a binary that performs none of them.
The mechanism sits in the C standard's "as-if" rule, which says a compiler may transform a program in any way it likes, as long as a program running the compiled code produces the same observable behavior as one running the source. The language does not require the binary to preserve every internal step the developer wrote. If a bounds check, a memory-clearing call, or an input-validation branch is not strictly required to match the abstract machine's behavior, the compiler can drop it.
Domas pointed to specific buffer sizes, such as 17 or 33 bytes, where a check survives optimization, while sizes just above or below compile to binaries that do not perform the check at all. The cause is register pressure and the way the compiler lays the surrounding structure out: at one size the check fits in a free register, at the next it spills, and the optimizer decides the check is no longer worth the spill. The same source, recompiled for a different target, can flip between safe and unsafe without a line of code changing.
Compilers can also widen the gap between a check and the operation it guards. A check that runs immediately before a sensitive call, in source, can be reordered so the call happens first, opening a time-of-check-to-time-of-use (TOCTOU) window, in which another thread or process changes the value between the check and the use, and the program never notices. The C abstract machine says almost nothing about external-world interaction, so this kind of move is legal as long as a single-threaded observer cannot see the difference.
Memory-clearing is the most counter-intuitive casualty. A developer who zeroes a password buffer before freeing it has done the right thing in source. The compiler, asked to be equivalent, is allowed to drop the zeroing entirely, because the bytes are dead by the time they would have been overwritten by the free. The binary is faithful to the abstract machine, and the password is still on the heap.
Domas reported that an AI-assisted scan of roughly 500 million lines of open-source C code surfaced about 300 patterns where the same kind of optimization is likely to remove a check. The figure is a claim from the talk and is not yet tied to a primary artifact, and is best read as a lower bound on the size of the surface, not a count of confirmed bugs.
The audience at Black Hat, and a Hacker News thread that followed the talk, pushed two obvious counter-arguments. Switching from GCC to Clang is not a fix: both honor the same standard, and both will delete the same check if the optimization is legal. Moving to Rust addresses whole categories of memory-safety bugs, but it does not turn the C compiler's habits off, and C dependencies stay C dependencies.
Turn the compiler's warnings on, and treat them as errors at the boundary. Run sanitizers such as AddressSanitizer, UndefinedBehaviorSanitizer, and MemorySanitizer on the build closest to what will ship. Inspect the optimized binary rather than the source when a check matters: read the disassembly, confirm the call site still branches to the validator, and treat the source as one input among several. Audit the exact binary that goes out the door, because the same source compiled with different flags or a different target can carry or lose a check.
The version of "secure C" that survives the optimizer is the version that has been tested after optimization. Anything less is a bet on what the compiler is allowed to do.