Linux выпилил strncpy: шесть лет, 360 патчей и функция, которой 50 лет

Ядро убрало C-функцию, которая тихо плодила баги с 1970-х. В треде сошлись двое: тот, кто впервые увидел strncpy полвека назад, и создатель языка D. Оба согласны в одном: где бы она ни появлялась, там обнаруживался баг.

Вкратце

strncpy убрали за «контринтуитивную семантику» вокруг NUL-терминатора и бессмысленное забивание нулями. Цифра «360 патчей» — это 360 использований, переписанных на безопасные вызовы, а не 360 багов.

Откуда она взялась: функцию написали, чтобы копировать 14-байтные имена файлов из ранних записей каталогов UNIX — дополненные нулями, но без терминатора. Для строк её не предназначали.

Что убрали и почему

Phoronix сообщает об удалении strncpy в Linux 7.2
Phoronix сообщает об удалении strncpy в Linux 7.2

Phoronix сообщает, что ядро Linux избавилось от API strncpy после примерно шести лет работы и 360 патчей: изменение попало в цикл 7.2. Причина, словами самого ядра, в том, что strncpy был «постоянным источником багов… из-за контринтуитивной семантики и поведения вокруг NUL-терминации, а ещё проблем с производительностью из-за избыточного забивания приёмника нулями». Один из комментаторов поправил подразумеваемый счёт жертв:

«Учтите: "360 патчей" — это 360 убранных использований strncpy, не обязательно багов». — комментатор, уточняющий подтекст заголовка

Функция была недоразумением с рождения

Лучший вклад в треде — кусок живой истории: strncpy ведёт себя так странно потому, что строковой функцией она не была вовсе:

«strncpy, изначально часть кода ядра UNIX, придумали, чтобы копировать имена файлов в записи каталога и обратно — а они состояли из 2-байтного номера inode и 14-байтного поля имени, дополненного нулями, но без нуля-терминатора. Я начал отговаривать коллег от неё в тот самый момент, когда впервые её увидел, лет 50 назад». — комментатор, вспоминающий исходное применение в записях каталогов UNIX

Этот единственный факт объясняет всю сагу из 360 патчей: процедуру, созданную чтобы заполнять фиксированное 14-байтное поле дополнением, десятилетиями применяли так, будто она безопасно копирует строки. А она не копирует. Создатель языка D подтвердил тот же узор с другого конца таймлайна:

«Когда меня просили ревьюить код на C, я всегда искал strncpy и всегда находил с ней баг». — Walter Bright, создатель языка программирования D

Исправление существовало 30 лет, и его блокировали

Самый острый разворот: безопасная замена была доступна целое поколение, но её не пускали:

«Напомню, что strlcpy у нас есть уже лет 30, но в мир Linux её так и не приняли из-за типичной мелочной грызни в опенсорсе». — комментатор об истории strlcpy

Баг возрастом 50 лет уходит на пенсию

Вот как выглядит технический долг на пике зрелости: функция, рождённая в 1970-х чтобы дополнять поля фиксированной ширины на диске, с тех пор принимаемая за копирование строк, десятилетиями защищаемая от более безопасной альтернативы, и наконец вырезанная из 360 мест вызова за шесть лет. Удаления никто не заметит, и в этом весь смысл: награда за изъятие острого инструмента — отсутствие будущего пореза. Два старейших голоса треда, один встретил strncpy 50 лет назад, другой охотится на неё в код-ревью, были единодушны: скатертью дорога, и что ж так долго.

Получайте такие разборы каждый день

Главные истории Hacker News — на email, в Telegram или RSS.

Следующая новость · 24 из 30 Читать дальше
🚀Tech

Он спрятал целую веб-страницу в фавиконку. В треде нашлось три способа чище

Хак упаковывает HTML страницы в пиксели фавиконки, по три байта на пиксель, и рендерит её крошечным загрузчиком. Мило. Потом исследователь безопасности заметил, что загрузчик можно выкинуть вовсе через полиглот HTML/PNG, а кто-то вспомнил deCSS, спрятанный в фавиконке ещё в 2000-м.

★ 293 · 💬 99 · timwehrle.de · 3 мин