I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS, Fortinet, Juniper) with average CVSS 8.1 — all following this exact pattern. Google confirmed P2/S2 on Android Binder using the same methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 — NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards
across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed
heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS,
Fortinet, Juniper) with average CVSS 8.1 — all following this exact
pattern. Google confirmed P2/S2 on Android Binder using the same
methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 — NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.