19 июня Линус Торвальдс принял merge, окончательно удаливший из ядра функцию strncpy. На это ушло шесть лет работы, 362 коммита и 70 разработчиков. Пример того, почему просто заменить небезопасную функцию в C вовсе не просто.
Буква «n» в названии создаёт иллюзию контроля: strncpy(dst, src, n) копирует максимум n байт. Однако документация предупреждает, что это не строковая функция, она создаёт
null-padded character sequence. Появившись в AT&T Unix около 1979 года для работы с именами файлов в директориях (поля фиксированной ширины), strncpy десятилетиями использовалась в обычном коде как безопасная замена strcpy. Но если длина источника >= n, терминальный \0 не ставится, и любой strlen или printk улетит за буфер. Если источник короче n, то весь остаток до n забивается нулями, что порождает ненужную нагрузку.Заменить strncpy одной функцией невозможно: под разные намерения нужен разный инструмент:
strscpy() — для нормальной строки с терминатором.strscpy_pad() — то же с обнулением хвоста.strtomem() / strtomem_pad() — для полей фиксированной ширины без терминатора.memcpy_and_pad() — для bounded-копии из источника, который может не иметь завершающего нуля.memtostr() / memtostr_pad() — обратный случай.memcpy() — если это вообще не строка.Один и тот же вызов
strncpy требовал ручного чтения контекста: строка это или бинарное поле, нужен ли ноль, нужен ли padding. 362 раза, и каждый раз разное решение.В вашей кодовой базе
strncpy, скорее всего, всё ещё живёт как безопасный вариант. Это не баг в трекере, это код, который надо перечитать. И главная работа будет не в замене функции, а в том, чтобы понять, что лежит в каждом буфере. Ядру на это понадобилось шесть лет и 70 человек — на API, который выглядел как безопасный десятилетиями.Linux / Линукс 🥸