Из ядра Linux выпилили strncpy 19 июня Линус Торвальдс принял merge, окончательно удаливший из ядра функцию strncpy.
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