← На главную

Unsigned типы: отказ от них ведёт к уязвимостям как в qmail

08.07.2026 19:35 · hackernews

Программисты слишком часто используют знаковые (signed) целые числа, хотя в подавляющем большинстве случаев числа в коде никогда не бывают отрицательными. Автор убеждает: беззнаковые (unsigned) типы стоит применять намного чаще, а популярные аргументы против них — ошибочны.

Главный страх — что unsigned опаснее из-за риска андерфлоу (ухода в ноль и ниже). В ответ автор показывает, как легко обойти эту проблему. Например, обратный цикл for (size_t i = size - 1; i < size; i--) использует то, что в C и C++ андерфлоу беззнаковых типов определён и предсказуем — после нуля i станет огромным числом, условие i < size сработает как надо. Никаких узких мест. В Rust для этого есть (0..size).rev().

Аргумент про разницу двух чисел тоже не выдерживает критики. Если y > x, андерфлоу грозит и знаковым типам (в C и C++ это вообще неопределённое поведение). Для unsigned решение тривиально: delta = max(x, y) - min(x, y).

Знаменитая формула (low + high) / 2 для середины интервала ломается при переполнении суммы. Переписывание на low + (high - low) / 2 тоже не спасает при крайних значениях. Беззнаковая версия хотя бы не даст выхода за границы массива, даже если результат математически неверен. Полноценное безопасное решение — std::midpoint в C++.

Аргумент про переполнение при умножении (например, для выделения памяти) работает для обоих типов. Но для unsigned есть простое решение: if (x * y < max), где max — максимум типа.

Сигнальные значения (отрицательные числа как коды ошибок) — плохая практика. Их легко заменить на Option, enum или возврат пары значений, что и делают в Rust, Go, Odin.

Главный довод «за» unsigned: код становится проще и безопаснее. Автор уверяет, что за пять лет использования беззнаковых чисел в новых проектах ни разу не пожалел. При этом даже в Google C++ Style Guide unsigned не рекомендуют — но именно такой код, по мнению автора, ведёт к реальным уязвимостям вроде той, что нашли в qmail спустя годы.

Читать оригинал →