
Из ядра Linux выпилили strncpy: шесть лет, 362 коммита, одна функция
opium 8 минут назад Из ядра Linux выпилили strncpy: шесть лет, 362 коммита, одна функция 2 мин 179 Настройка Linux * Open source * Информационная безопасность * Программирование * 19 июня Торвальдс влил merge, который...
Anthropic — What company has the best second artificial intelligence model at the end of June?
Вот важная новость с фронта ИИ: opium 8 минут назад Из ядра Linux выпилили strncpy: шесть лет, 362 коммита, одна функция 2 мин 179 Настройка Linux * Open source * Информационная безопасность * Программирование * 19 июня Торвальдс влил merge, который вычистил из ядра Linux функцию strncpy. Шесть лет работы, 362 коммита, семьдесят человек. Ради одной функции из стандартной библиотеки C.
Звучит как анекдот про бюрократию. На деле это наглядный разбор того, почему «просто заменить небезопасную функцию» в C — совсем не «просто», даже когда принципиального спора о замене нет. Почему её считают «безопасной»Из-за буквы n.
Технические детали
strcpy копирует до нуля и легко улетает за буфер, а strncpy(dst, src, n) берёт максимум n байт — выглядит как та же функция, но с ремнём безопасности. Её и в самом ядре нашли в сотнях мест; что уж говорить про прикладной код. man про strncpy пишет прямым текстом: функция создаёт «null-padded character sequence, not a string».
Это не про строки вообще. Появилась она в Edition 7 AT&T Unix около 1979 года — под имена файлов в directory entries, где поле фиксированной ширины и могло содержать ноль, один или несколько хвостовых нулей. Такие fixed-width поля живы и сейчас, но это редкий частный случай — а strncpy сорок лет тащат в обычный код как «strcpy, который не стреляет в ногу».
Стреляет, просто тихо. Если strlen(src) >= n, то strncpy запишет ровно n байт и не поставит завершающий \0. Дальше любой strlen, strcmp или printk("%s", …) уходит читать за буфер: мусор, чужая память, в плохой день — утечка данных.
Отраслевые последствия
А если наоборот, strlen(src) < n, остаток буфера до n забивается нулями: скопировали четыре байта в буфер на четыре килобайта — получите 4092 лишних записи на ровном месте. В документации ядра API так и назвали — ambiguous и fragile: по одному вызову не понять, чего хотел автор. Поле фиксированной ширины?
Где зарыты шесть летЗамена — это не «найти и поменять на безопасный аналог». Безопасного аналога нет. Под разные намерения — свой набор: strscpy() для нормальной C-строки с \0, strscpy_pad() — то же с обнулением хвоста, strtomem() / strtomem_pad() для полей фиксированной ширины без терминатора, memcpy_and_pad() для bounded-копии из источника, который может быть не завершён нулём, memtostr() / memtostr_pad() для обратного случая, ну и обычный memcpy(), если это вообще не строка.
Восемь функций там, где раньше была одна. И sed -i 's/strncpy/strscpy/g' тут не работает в принципе, потому что верный ответ зависит от намерения автора:/* имя в поле фиксированной ширины внутри on-disk структуры — \0 не нужен */ strncpy(de->name, name, sizeof(de->name)); // → strtomem_pad() /* а это уйдёт в printk("%s", buf) — без \0 здесь read-overflow */ strncpy(buf, src, sizeof(buf)); // → strscpy() Один и тот же вызов, разный верный ответ. И так 362 раза: каждый надо открыть и прочитать глазами — это строка или бинарное поле, нужен ли ноль, нужен ли padding, завершён ли источник, известен ли размер приёмника на компиляции.
Этот прогресс даёт важные сигналы о будущем отрасли, и технологический мир внимательно наблюдает.





