Если взять самую популярную C-шную библиотеку вроде curl и попытаться найти уязвимость, результат может быть неочевидным. Например, функция curl_getenv — простой враппер для чтения переменных среды. Если передать ей NULL, программа просто упадёт с segfault. Очевидная проблема с памятью, верно? Но сообщать об этом как о CVE в curl никто не будет. Потому что это не баг библиотеки, а ошибка использования — пользователь нарушил неявный контракт. В C или C++ такой контракт часто невозможно прописать в типе данных, а описывать все варианты неправильного вызова документация не обязана. Если бы каждую подобную ситуацию оформляли как CVE, C/C++-библиотеки утонули бы в миллионах отчётов.
С Rust ситуация кардинально другая. Возьмём hyper — аналог curl в Rust. Если бы его функция без unsafe принимала None и падала, это стало бы CVE мгновенно. Потому что в коде пользователя нет unsafe блоков, значит, ошибка памяти — это звуковая дыра (soundness hole) в самой библиотеке. Логика простая: если в safe Rust есть способ вызвать библиотеку так, чтобы получить memory bug, виновата библиотека, а не вызывающий код. Разработчики Rust считают это принципиальным — они открывают CVE на сам факт существования опасного API, даже если никто в реальности им ещё не воспользовался.
Автор поста подчёркивает: сравнивать «сырые» числа CVE между Rust и C/C++ бессмысленно. В Rust стандарт намного строже — если функция не помечена unsafe, ты просто не можешь использовать её неправильно с точки зрения безопасности памяти. Любой сбой — баг библиотеки. В C же все функции по умолчанию unsafe, и ответственность за корректный вызов целиком ложится на программиста. Даже безупречная библиотека вроде curl не защитит миллионы C-программ от случайного segfault — только «держать её правильно» никто не гарантирует.