When the compiler lies: breaking memory safety in safe Go
6 hours ago
- #Go Compiler
- #Security Bugs
- #Memory Safety
- The author discovered two compiler bugs in Go (up to version 1.26.1) that broke memory safety using only safe Go code, without unsafe imports, CGO, custom assembly, or data races.
- Bug 1 involved the 'prove' optimization pass incorrectly handling signed integer wrap in loops, allowing array bounds checks to be eliminated when indices could become negative, leading to control-flow hijacking.
- Bug 2 occurred during SSA lowering, where a no-op conversion caused the compiler to skip careful copying for overlapping arrays, resulting in memory corruption and potential exploitation.
- Both bugs stemmed from the compiler mistakenly upgrading 'probably safe' to 'proved safe', highlighting that memory safety depends on the entire toolchain, not just the language.
- The author found that the root cause of Bug 1 was a change they had introduced over three years earlier, revealed by 'git blame', shifting their initial thrill to a humbling realization.
- The Go security team responded quickly to the reports (within minutes), and the author plans to publish full details after fixed releases are widely available.